🤖

Spring Boot + jOOQのテスト

2024/09/16に公開

前回Spring BootにjOOQとFlywayを導入したので、今回はテストを試す

https://zenn.dev/kentama/articles/1c47407335d59e

環境

  • Spring Boot: 3.3.3
  • jOOQ: 3.19.11
  • Flyway: 10.10.0
  • PostgreSQL: 15
  • Kotlin: 1.9.25

準備

テスト対象のクラスを作成する

UsersRepository.kt
@Component
class UsersRepository(
    private val dsl: DSLContext
) {
    fun findAll(): List<Users> = dsl.selectFrom(Tables.USERS).fetchInto(Users::class.java)

    fun save(username: String, email: String): Users? = dsl.insertInto(Tables.USERS)
        .set(Tables.USERS.USERNAME, username)
        .set(Tables.USERS.EMAIL, email)
        .returning()
        .fetchOneInto(Users::class.java)
}

テストの作成

テストデータを src/test/resources に作成する

test-data.sql
INSERT INTO users (username, email)
VALUES ('admin', 'admin@example.com')
     , ('member', 'member@example.com');

テストクラスの作成

  • テストクラスには @JooqTest を付与する
  • テストデータの投入に @Sql を使う
UsersRepositoryTest.kt
@JooqTest
@Sql("/test-data.sql") // テストデータを投入
class UsersRepositoryTest {

    @Autowired
    lateinit var dsl: DSLContext

    lateinit var usersRepository: UsersRepository

    @BeforeEach
    fun setup() {
        usersRepository = UsersRepository(dsl)
    }

    @Test
    fun findAll() {
        val actual = usersRepository.findAll()

        assertEquals(2, actual.size)
    }

    @Test
    fun save() {
        val actual = usersRepository.save("name", "email")

        assertEquals("name", actual?.username)
        assertEquals("email", actual?.email)
    }
}

DBを起動し、テストが通ればOK

Testcontainersを使ったテスト

作成したテストはDBが起動している前提なので、Testcontainersを使用して使い捨てのDBを用意してテストするようにする

環境

  • Testcontainers: 1.19.8

準備

build.gradle.ktsに以下3つを追加する

dependencies {
    // ...
    testImplementation("org.springframework.boot:spring-boot-testcontainers")
    testImplementation("org.testcontainers:junit-jupiter")
    testImplementation("org.testcontainers:postgresql")
}

以下2つのファイルを作成する

TestcontainersConfiguration.kt
@TestConfiguration(proxyBeanMethods = false)
class TestcontainersConfiguration {

    @Bean
    @ServiceConnection
    fun postgresContainer(): PostgreSQLContainer<*> {
        return PostgreSQLContainer(DockerImageName.parse("postgres:15-alpine"))
    }
}
TestDemoApplication.kt
fun main(args: Array<String>) {
    fromApplication<DemoApplication>().with(TestcontainersConfiguration::class).run(*args)
}

テストクラスの修正

@Import(TestcontainersConfiguration::class) を付与すればOK

UsersRepositoryTest.kt
+@Import(TestcontainersConfiguration::class)
@JooqTest
@Sql("/test-data.sql")
class UsersRepositoryTest {
    // ...
}

テストを実行して、コンテナが起動とそのコンテナに対してFlywayがマイグレーションしていることが確認できれば成功

2024-09-16T16:23:13.927+09:00  INFO 45757 --- [demo] [    Test worker] tc.postgres:15-alpine                    : Container is started (JDBC URL: jdbc:postgresql://localhost:64704/test?loggerLevel=OFF)
2024-09-16T16:23:14.223+09:00  INFO 45757 --- [demo] [    Test worker] org.flywaydb.core.FlywayExecutor         : Database: jdbc:postgresql://localhost:64704/test (PostgreSQL 15.2)
2024-09-16T16:23:14.250+09:00  INFO 45757 --- [demo] [    Test worker] o.f.c.i.s.JdbcTableSchemaHistory         : Schema history table "public"."flyway_schema_history" does not exist yet
2024-09-16T16:23:14.252+09:00  INFO 45757 --- [demo] [    Test worker] o.f.core.internal.command.DbValidate     : Successfully validated 3 migrations (execution time 00:00.013s)
2024-09-16T16:23:14.265+09:00  INFO 45757 --- [demo] [    Test worker] o.f.c.i.s.JdbcTableSchemaHistory         : Creating Schema History table "public"."flyway_schema_history" ...

Discussion