Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions modules/GuildManager/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<groupId>com.github.PlaceholderAPI</groupId>
<artifactId>PlaceholderAPI</artifactId>
<version>2.11.1</version>
<scope>provided</scope>
</dependency>
Expand All @@ -120,6 +120,18 @@
<version>5.6.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.5.1</version>
<scope>test</scope>
</dependency>
</dependencies>


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mcatk.guildmanager.command;

import com.mcatk.guildmanager.GuildManager;
import com.mcatk.guildmanager.GuildItem;
import com.mcatk.guildmanager.Msg;
import com.mcatk.guildmanager.exceptions.ParaLengthException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,29 @@ public HashMap<String, Guild> getAllGuilds() {
g.setCash(rs.getInt("guild_cash"));
g.setResidenceFLag(rs.getBoolean("guild_has_residence"));
g.setHasChangedName(rs.getBoolean("guild_has_changed_name"));
g.setMembers(getMembersFromSQL(g.getId()));
guilds.put(g.getId(), g);
}
} catch (SQLException e) {
e.printStackTrace();
}

try (PreparedStatement ps = getConnection().prepareStatement(SqlCommand.GET_ALL_MEMBERS.toString())) {
ResultSet rs = ps.executeQuery();
while (rs.next()) {
Member m = new Member(
rs.getString("player_id"),
rs.getString("guild_id"),
rs.getInt("player_contribution"),
rs.getBoolean("player_is_advanced")
);
Guild g = guilds.get(m.getGuildID());
if (g != null) {
g.getMembers().add(m);
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a member's guild_id doesn't match any existing guild in the guilds map, the member is silently ignored (the null check prevents adding it to any guild). While this is defensive programming, it may hide data integrity issues where members reference non-existent guilds. Consider logging a warning when this occurs to help detect orphaned member records in the database.

Suggested change
g.getMembers().add(m);
g.getMembers().add(m);
} else {
System.err.println("[JdbcGuildRepository] Orphaned member record: player_id=" + m.getPlayerID()
+ " references non-existent guild_id=" + m.getGuildID());

Copilot uses AI. Check for mistakes.
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return guilds;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public enum SqlCommand {
GET_PLAYER(
"SELECT * FROM player_guild WHERE player_id = ?"
),
GET_ALL_MEMBERS(
"SELECT * FROM player_guild"
),
GET_ALL_GUILDS(
"SELECT * FROM guild"
),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.mcatk.guildmanager.core.repository.jdbc;

import com.mcatk.guildmanager.core.config.DbConfig;
import com.mcatk.guildmanager.models.Guild;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import statement for Mockito is unused. The test uses static imports for the mock methods (mock, when, verify, times, anyString, contains) from Mockito, but doesn't directly reference the Mockito class itself. Consider removing this unused import.

Suggested change
import org.mockito.Mockito;

Copilot uses AI. Check for mistakes.

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.contains;
import static org.mockito.Mockito.*;

public class JdbcGuildRepositoryTest {

private JdbcGuildRepository repository;
private Connection mockConnection;
private ResultSet mockResultSetGuilds;
private ResultSet mockResultSetMembers;

@Before
public void setUp() throws Exception {
DbConfig config = new DbConfig("localhost", 3306, "test", "user", "pass");
repository = new JdbcGuildRepository(config);

mockConnection = mock(Connection.class);
mockResultSetGuilds = mock(ResultSet.class);
mockResultSetMembers = mock(ResultSet.class);

// Inject mock connection
Field connectionField = JdbcGuildRepository.class.getDeclaredField("connection");
connectionField.setAccessible(true);
connectionField.set(repository, mockConnection);

when(mockConnection.isClosed()).thenReturn(false);
}

@Test
public void testGetAllGuilds_Optimization() throws SQLException {
PreparedStatement psGuilds = mock(PreparedStatement.class);
PreparedStatement psMembers = mock(PreparedStatement.class);

// Setup mock calls for prepareStatement
when(mockConnection.prepareStatement(contains("FROM guild"))).thenReturn(psGuilds);
// The optimized code fetches all members at once
when(mockConnection.prepareStatement(contains("SELECT * FROM player_guild"))).thenReturn(psMembers);

when(psGuilds.executeQuery()).thenReturn(mockResultSetGuilds);
when(psMembers.executeQuery()).thenReturn(mockResultSetMembers);

// Setup 5 guilds
when(mockResultSetGuilds.next()).thenReturn(true, true, true, true, true, false);
when(mockResultSetGuilds.getString("guild_id")).thenReturn("g1", "g2", "g3", "g4", "g5");
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test only mocks the guild_id field from the ResultSet, but the actual getAllGuilds() method retrieves multiple fields for each guild (guild_name, guild_chairman, guild_vice_chairman_1, guild_vice_chairman_2, guild_level, guild_points, guild_cash, guild_has_residence, guild_has_changed_name). This will cause NullPointerExceptions or default values when those getters are called on the ResultSet. You should add mock return values for all these fields to ensure the test accurately reflects the actual behavior.

Suggested change
when(mockResultSetGuilds.getString("guild_id")).thenReturn("g1", "g2", "g3", "g4", "g5");
when(mockResultSetGuilds.getString("guild_id")).thenReturn("g1", "g2", "g3", "g4", "g5");
when(mockResultSetGuilds.getString("guild_name")).thenReturn("Guild1", "Guild2", "Guild3", "Guild4", "Guild5");
when(mockResultSetGuilds.getString("guild_chairman")).thenReturn("Chairman1", "Chairman2", "Chairman3", "Chairman4", "Chairman5");
when(mockResultSetGuilds.getString("guild_vice_chairman_1")).thenReturn("Vice1_1", "Vice1_2", "Vice1_3", "Vice1_4", "Vice1_5");
when(mockResultSetGuilds.getString("guild_vice_chairman_2")).thenReturn("Vice2_1", "Vice2_2", "Vice2_3", "Vice2_4", "Vice2_5");
when(mockResultSetGuilds.getInt("guild_level")).thenReturn(1, 2, 3, 4, 5);
when(mockResultSetGuilds.getInt("guild_points")).thenReturn(10, 20, 30, 40, 50);
when(mockResultSetGuilds.getInt("guild_cash")).thenReturn(100, 200, 300, 400, 500);
when(mockResultSetGuilds.getBoolean("guild_has_residence")).thenReturn(false, false, false, false, false);
when(mockResultSetGuilds.getBoolean("guild_has_changed_name")).thenReturn(false, false, false, false, false);

Copilot uses AI. Check for mistakes.

// Members return nothing for now
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states "Members return nothing for now" but the code immediately below it sets up 2 members with player_id, guild_id, player_contribution, and player_is_advanced values. This comment is misleading and should be updated to reflect the actual test setup, such as "Setup 2 members for guilds g1 and g2".

Suggested change
// Members return nothing for now
// Setup 2 members for guilds g1 and g2

Copilot uses AI. Check for mistakes.
when(mockResultSetMembers.next()).thenReturn(true, true, false);
when(mockResultSetMembers.getString("player_id")).thenReturn("player1", "player2");
when(mockResultSetMembers.getString("guild_id")).thenReturn("g1", "g2");
when(mockResultSetMembers.getInt("player_contribution")).thenReturn(100, 200);
when(mockResultSetMembers.getBoolean("player_is_advanced")).thenReturn(true, false);

HashMap<String, Guild> result = repository.getAllGuilds();

assertEquals(5, result.size());

// Verify optimization:
// 1 call for guilds
// 1 call for all members
// Total 2 calls to prepareStatement
verify(mockConnection, times(2)).prepareStatement(anyString());

// Verify Data Mapping
assertEquals(1, result.get("g1").getMembers().size());
assertEquals("player1", result.get("g1").getMembers().get(0).getId());

assertEquals(1, result.get("g2").getMembers().size());
assertEquals("player2", result.get("g2").getMembers().get(0).getId());

assertEquals(0, result.get("g3").getMembers().size());
}
}
Loading