🐈‍⬛

Spring Boot ・Testcontainers・Flyway でテスト環境を作成

に公開

Testcontainersを使用すると、Dockerコンテナ上でデータベースやミドルウェアを立ち上げてテストを行えます。Spring BootアプリケーションにPostgreSQLとFlywayを組み合わせて、テストを行います。

環境

  • Java21
  • Spring Boot 3.4.4

依存関係

dependencies {
    implementation("org.springframework.boot:spring-boot-starter:3.4.4")
    implementation("org.springframework.boot:spring-boot-starter-jdbc:3.4.4")

    runtimeOnly("org.postgresql:postgresql:42.7.5")

    implementation("org.flywaydb:flyway-database-postgresql:11.7.2")

    testImplementation("org.springframework.boot:spring-boot-starter-test:3.4.4")
    testImplementation("org.springframework.boot:spring-boot-testcontainers:3.4.4")
    testImplementation("org.testcontainers:postgresql:1.20.6")
}

プロジェクト構成

構成
src/
├── main/
│   └── java/
│       └── com/
│           └── example/
│               └── Application.java
├── test/
│   ├── java/
│   │   └── com/
│   │       └── example/
│   │           ├── ExampleTest.java
│   │           └── TestContainersConfiguration.java
│   └── resources/
│       └── db/
│           └── migration/
│               └── V00__init.sql

アプリケーション

Application.java

Application.java
package org.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Spring Bootアプリケーションのエントリーポイントです。

ExampleTest.java

ExampleTest.java
package org.example;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

@SpringBootTest
@Import(TestContainersConfiguration.class)
public class ExampleTest {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Test
    void test() {
        List<String> names = jdbcTemplate.queryForList("select name from test order by id", String.class);
        Assertions.assertEquals(3, names.size());
        Assertions.assertEquals("テスト1", names.get(0));
        Assertions.assertEquals("テスト2", names.get(1));
        Assertions.assertEquals("テスト3", names.get(2));
    }
}

このテストクラスはSpring Bootのテストコンテキストを使って、Testcontainersで起動したPostgreSQLに対してSQLを実行しています。

  • @Import(TestContainersConfiguration.class)で、テスト用のDB設定を読み込みます
  • JdbcTemplateを使ってSQLを直接発行しています
  • Flywayによって初期データが投入されるため実データでのテストが可能です

TestContainersConfiguration.java

TestContainersConfiguration.java
package org.example;

import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.DockerImageName;

@TestConfiguration(proxyBeanMethods = false)
public class TestContainersConfiguration {
    @Bean
    @ServiceConnection
    PostgreSQLContainer<?> postgres() {
        return new PostgreSQLContainer<>(DockerImageName.parse("postgres:17.4"));
    }

    @DynamicPropertySource
    void properties(DynamicPropertyRegistry registry) {
        registry.add("spring.flyway.enabled", () -> "true");
    }
}

このクラスは、Spring Bootテスト環境でPostgreSQLコンテナを起動し、Springアプリケーションと自動的に接続する設定です。

  • @ServiceConnectionを使うことでspring.datasource.*の設定が不要になります
  • @DynamicPropertySourceにより、Flywayの自動マイグレーションを有効化しています

初期データ

V00__init.sql

V00__init.sql
create table test (
  id integer generated always as identity primary key,
  name text
);

insert into test (name) values('テスト1');
insert into test (name) values('テスト2');
insert into test (name) values('テスト3');

Flywayが実行するSQLファイルです。テストを実行すると、ここに記述されている内容がPostgreSQLに反映されます。

実行結果ログ抜粋

TestcontainersがDockerと接続

Connected to docker: 
  Server Version: 27.4.0
  API Version: 1.47

PostgreSQLコンテナが起動

Container is started (JDBC URL: jdbc:postgresql://localhost:52965/test)

Flywayによるマイグレーション

Migrating schema "public" to version "00 - init"
Successfully applied 1 migration to schema "public", now at version v00 (execution time 00:00.005s)

まとめ

Spring Boot、Testcontaners、Flywayを使用して以下のことが実行できました。

  • DockerベースのPostgreSQLを使ってテスト
  • Flywayでマイグレーション
  • @ServiceConnectionを使用してPostgreSQLへ接続

参考リンク

Discussion