From c7f835da0dd232fb56fd0e4f955ca1aacc9e439a Mon Sep 17 00:00:00 2001 From: P0nk Date: Thu, 26 Sep 2024 19:51:18 +0200 Subject: [PATCH] Add DatabaseTest to easily test repositories --- src/test/java/database/DatabaseTest.java | 126 ++++++++++++++++++ .../character/CharacterSaverTest.java | 84 ++---------- src/test/java/testutil/TestData.java | 39 ------ 3 files changed, 134 insertions(+), 115 deletions(-) create mode 100644 src/test/java/database/DatabaseTest.java delete mode 100644 src/test/java/testutil/TestData.java diff --git a/src/test/java/database/DatabaseTest.java b/src/test/java/database/DatabaseTest.java new file mode 100644 index 0000000000..ca142dd6df --- /dev/null +++ b/src/test/java/database/DatabaseTest.java @@ -0,0 +1,126 @@ +package database; + +import client.CharacterStats; +import config.ServerConfig; +import config.YamlConfig; +import database.account.Account; +import database.account.AccountRepository; +import database.character.CharacterRepository; +import database.migration.FlywayRunner; +import org.jdbi.v3.core.Handle; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.TestInstance; +import org.postgresql.ds.PGSimpleDataSource; +import org.testcontainers.containers.MySQLContainer; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import testutil.GeneratedIds; +import tools.DatabaseConnection; + +import java.time.Duration; +import java.time.LocalDate; +import java.util.List; + +@Testcontainers +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public abstract class DatabaseTest { + private static final String MYSQL_VERSION = "8.4"; + private static final String POSTGRES_VERSION = "16.4"; + private static final String SCHEMA_NAME = "cosmic"; + + @Container + static MySQLContainer mySql = new MySQLContainer<>("mysql:%s".formatted(MYSQL_VERSION)); + + @Container + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:%s".formatted(POSTGRES_VERSION)); + + protected PgDatabaseConnection pgConnection; + protected GeneratedIds testIds; + + @BeforeAll + void setUp() { + prepareMysqlConnection(); + runDbMigrations(); + this.pgConnection = createPgConnection(); + } + + // Not using this, but due to the nature of how the db connections are set up, the application requires + // a real database to connect to. + private void prepareMysqlConnection() { + ServerConfig serverConfig = new ServerConfig(); + serverConfig.DB_URL_FORMAT = "%s"; + serverConfig.DB_HOST = mySql.getJdbcUrl(); + serverConfig.DB_USER = mySql.getUsername(); + serverConfig.DB_PASS = mySql.getPassword(); + serverConfig.INIT_CONNECTION_POOL_TIMEOUT = 60; + YamlConfig.config.server = serverConfig; + DatabaseConnection.initializeConnectionPool(); + } + + private void runDbMigrations() { + PgDatabaseConfig config = PgDatabaseConfig.builder() + .url(postgres.getJdbcUrl()) + .schema(SCHEMA_NAME) + .adminUsername(postgres.getUsername()) + .adminPassword(postgres.getPassword()) + .username(postgres.getUsername()) + .password(postgres.getPassword()) + .poolInitTimeout(Duration.ofSeconds(60)) + .clean(false) + .build(); + new FlywayRunner(config).migrate(); + } + + private PgDatabaseConnection createPgConnection() { + return new PgDatabaseConnection(createDataSource()); + } + + private PGSimpleDataSource createDataSource() { + PGSimpleDataSource dataSource = new PGSimpleDataSource(); + dataSource.setUrl(postgres.getJdbcUrl()); + dataSource.setCurrentSchema(SCHEMA_NAME); + dataSource.setUser(postgres.getUsername()); + dataSource.setPassword(postgres.getPassword()); + return dataSource; + } + + @BeforeEach + void insertTestData() { + int accountId = insertAccount(pgConnection); + try (Handle handle = pgConnection.getHandle()) { + int chrId = insertChr(handle, accountId); + this.testIds = new GeneratedIds(accountId, chrId); + } + } + + private static int insertAccount(PgDatabaseConnection connection) { + Account account = Account.builder() + .name("accountname") + .password("accountpassword") + .birthdate(LocalDate.now()) + .build(); + return new AccountRepository(connection).insert(account); + } + + private static int insertChr(Handle handle, int accountId) { + CharacterRepository chrRepository = new CharacterRepository(); + CharacterStats stats = CharacterStats.builder() + .account(accountId) + .name("chrname") + .build(); + return chrRepository.insert(handle, stats); + } + + @AfterEach + void deleteTestData() { + List.of("chr", "account").forEach(this::clearTable); + } + + private void clearTable(String tableName) { + String sql = "DELETE FROM %s".formatted(tableName); + pgConnection.getHandle().execute(sql); + } +} diff --git a/src/test/java/database/character/CharacterSaverTest.java b/src/test/java/database/character/CharacterSaverTest.java index ad84c4e7a9..77e7b717d5 100644 --- a/src/test/java/database/character/CharacterSaverTest.java +++ b/src/test/java/database/character/CharacterSaverTest.java @@ -3,111 +3,43 @@ package database.character; import client.Character; import client.CharacterStats; import client.MonsterBook; -import config.ServerConfig; -import config.YamlConfig; -import database.PgDatabaseConfig; -import database.PgDatabaseConnection; -import database.migration.FlywayRunner; +import database.DatabaseTest; import database.monsterbook.MonsterCardRepository; import org.jdbi.v3.core.Handle; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import org.postgresql.ds.PGSimpleDataSource; -import org.testcontainers.containers.MySQLContainer; -import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import testutil.GeneratedIds; -import testutil.TestData; -import tools.DatabaseConnection; -import java.time.Duration; import java.util.Collections; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.when; @Testcontainers -class CharacterSaverTest { - private static final String MYSQL_VERSION = "8.4"; - private static final String POSTGRES_VERSION = "16.4"; - private static final String SCHEMA_NAME = "cosmic"; - - @Container - static MySQLContainer mySql = new MySQLContainer<>("mysql:%s".formatted(MYSQL_VERSION)); - - @Container - static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:%s".formatted(POSTGRES_VERSION)); - - private PgDatabaseConnection pgConnection; +class CharacterSaverTest extends DatabaseTest { private CharacterSaver characterSaver; @BeforeEach - void setUp() { - prepareMysqlConnection(); - runDbMigrations(); - PgDatabaseConnection pgDatabaseConnection = createPgConnection(); - this.pgConnection = pgDatabaseConnection; - this.characterSaver = new CharacterSaver(pgDatabaseConnection, new CharacterRepository(), - new MonsterCardRepository(pgDatabaseConnection)); - } - - // Not using this, but due to the nature of how the db connections are set up, the application requires - // a real database to connect to. - private void prepareMysqlConnection() { - ServerConfig serverConfig = new ServerConfig(); - serverConfig.DB_URL_FORMAT = "%s"; - serverConfig.DB_HOST = mySql.getJdbcUrl(); - serverConfig.DB_USER = mySql.getUsername(); - serverConfig.DB_PASS = mySql.getPassword(); - serverConfig.INIT_CONNECTION_POOL_TIMEOUT = 60; - YamlConfig.config.server = serverConfig; - DatabaseConnection.initializeConnectionPool(); - } - - private void runDbMigrations() { - PgDatabaseConfig config = PgDatabaseConfig.builder() - .url(postgres.getJdbcUrl()) - .schema(SCHEMA_NAME) - .adminUsername(postgres.getUsername()) - .adminPassword(postgres.getPassword()) - .username(postgres.getUsername()) - .password(postgres.getPassword()) - .poolInitTimeout(Duration.ofSeconds(60)) - .clean(false) - .build(); - new FlywayRunner(config).migrate(); - } - - private PgDatabaseConnection createPgConnection() { - return new PgDatabaseConnection(createDataSource()); - } - - private PGSimpleDataSource createDataSource() { - PGSimpleDataSource dataSource = new PGSimpleDataSource(); - dataSource.setUrl(postgres.getJdbcUrl()); - dataSource.setCurrentSchema(SCHEMA_NAME); - dataSource.setUser(postgres.getUsername()); - dataSource.setPassword(postgres.getPassword()); - return dataSource; + void reset() { + this.characterSaver = new CharacterSaver(pgConnection, new CharacterRepository(), + new MonsterCardRepository(pgConnection)); } @Test void saveCharacter_shouldUpdateChrTable() { - GeneratedIds ids = TestData.create(pgConnection); Character mockChr = Mockito.mock(Character.class); when(mockChr.isLoggedin()).thenReturn(true); addEmptyMonsterBook(mockChr); when(mockChr.getCharacterStats()).thenReturn(CharacterStats.builder() - .id(ids.chrId()) + .id(testIds.chrId()) .level(200) .build()); - assertEquals(0, getChrLevel(ids.chrId())); + assertEquals(0, getChrLevel(testIds.chrId())); characterSaver.save(mockChr); - assertEquals(200, getChrLevel(ids.chrId())); + assertEquals(200, getChrLevel(testIds.chrId())); } private static void addEmptyMonsterBook(Character mockChr) { diff --git a/src/test/java/testutil/TestData.java b/src/test/java/testutil/TestData.java deleted file mode 100644 index dadb56b8f7..0000000000 --- a/src/test/java/testutil/TestData.java +++ /dev/null @@ -1,39 +0,0 @@ -package testutil; - -import client.CharacterStats; -import database.PgDatabaseConnection; -import database.account.Account; -import database.account.AccountRepository; -import database.character.CharacterRepository; -import org.jdbi.v3.core.Handle; - -import java.time.LocalDate; - -public class TestData { - - public static GeneratedIds create(PgDatabaseConnection connection) { - int accountId = insertAccount(connection); - try (Handle handle = connection.getHandle()) { - int chrId = insertChr(handle, accountId); - return new GeneratedIds(accountId, chrId); - } - } - - private static int insertAccount(PgDatabaseConnection connection) { - Account account = Account.builder() - .name("accountname") - .password("accountpassword") - .birthdate(LocalDate.now()) - .build(); - return new AccountRepository(connection).insert(account); - } - - private static int insertChr(Handle handle, int accountId) { - CharacterRepository chrRepository = new CharacterRepository(); - CharacterStats stats = CharacterStats.builder() - .account(accountId) - .name("chrname") - .build(); - return chrRepository.insert(handle, stats); - } -}