Testcontainers:実データベースによる統合テスト
TestcontainersでDocker上にPostgreSQLを起動し、実際のデータベースに対して統合テストを実行します。
「Testcontainers:実データベースによる統合テスト」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
Testcontainers を使う理由
H2 のインメモリデータベースは、PostgreSQL 固有の機能(JSON、全文検索、ON CONFLICT)をサポートしていません。Testcontainers はテスト中に実際の Docker コンテナを起動するため、本番環境と同一のデータベースを使用できます。
Testcontainers の依存関係を追加する
ビルドファイルに Testcontainers BOM と PostgreSQL モジュールを追加します。Spring Boot 3.1 以降には、管理対象の Testcontainers バージョンが含まれています。
// build.gradle:
testImplementation "org.testcontainers:junit-jupiter"
testImplementation "org.testcontainers:postgresql"
// Optionally use Spring Boot Testcontainers support:
testImplementation "org.springframework.boot:spring-boot-testcontainers"@Testcontainers と @Container
テストクラスに @Testcontainers を付け、コンテナを static な @Container フィールドとして宣言します。JUnit 5 がコンテナを自動的に起動および停止します。
@Testcontainers
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserRepositoryIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine")
.withDatabaseName("testdb")
.withUsername("test")
.withPassword("test");
}コンテナから DataSource を設定する
@DynamicPropertySource を使用して、コンテナの動的なポートと認証情報を Spring の DataSource 設定に注入します。
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}Spring Boot 3.1 の ServiceConnection
Spring Boot 3.1 以降では、@ServiceConnection が付与された Testcontainers の @Container Bean から DataSource が自動構成されるため、@DynamicPropertySource は必要ありません。
@Bean
@ServiceConnection
static PostgreSQLContainer<?> postgresContainer() {
return new PostgreSQLContainer<>("postgres:16-alpine");
}シングルトンコンテナパターン
テストクラスごとにコンテナを起動すると時間がかかります。Startables.deepStart() を使用する static フィールド、または抽象基底クラスによって、すべてのテストで 1 つのコンテナを共有します。
abstract class AbstractIntegrationTest {
@Container
static final PostgreSQLContainer<?> POSTGRES =
new PostgreSQLContainer<>("postgres:16-alpine").withReuse(true);
static { POSTGRES.start(); }
@DynamicPropertySource
static void props(DynamicPropertyRegistry r) {
r.add("spring.datasource.url", POSTGRES::getJdbcUrl);
r.add("spring.datasource.username", POSTGRES::getUsername);
r.add("spring.datasource.password", POSTGRES::getPassword);
}
}PostgreSQL 固有機能のテスト
Testcontainers を使用すると、JSON カラム、JSONB 演算子、全文検索、ON CONFLICT DO UPDATE をテストできます。これらは H2 では実現できません。
@Test
void jsonb_search_works() {
// Insert row with JSONB column, then query
List<Event> logins = repo.findByType("login");
assertEquals(1, logins.size());
}複数コンテナ: Compose
複数のサービスを必要とする統合テストでは、DockerComposeContainer を使用して完全なスタック(Postgres + Redis + Kafka)を実行します。
@Container
static DockerComposeContainer<?> compose = new DockerComposeContainer<>(
new File("src/test/resources/docker-compose.yml"))
.withExposedService("postgres", 5432)
.withExposedService("redis", 6379);Ryuk: 自動クリーンアップ
Testcontainers は Ryuk コンテナを使用して、JVM の終了時にコンテナを自動的に停止・削除します。テストが失敗した場合でも実行されるため、コンテナの残留を防止できます。
Testcontainers での @SpringBootTest
実際の Postgres コンテナに対してアプリケーション全体のスタック(コントローラー、サービス、リポジトリ)をテストするには、@DataJpaTest ではなく @SpringBootTest を使用します。
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Testcontainers
class FullIntegrationTest extends AbstractIntegrationTest {
@LocalServerPort int port;
@Autowired TestRestTemplate rest;
@Test
void end_to_end_user_creation() {
ResponseEntity<UserDto> r = rest.postForEntity("/api/users", createReq(), UserDto.class);
assertEquals(HttpStatus.CREATED, r.getStatusCode());
}
}コンテナイメージのキャッシュ
Testcontainers は取得した Docker イメージをローカルにキャッシュします。テスト実行中のダウンロード時間を避けるため、テストの開始前に CI でイメージを取得します(docker pull postgres:16-alpine)。
確認問題
Spring Boot 3.1 以降で、Testcontainers のコンテナを Spring の DataSource に自動接続するアノテーションはどれですか。
まとめ
Testcontainers は統合テスト用に実際の Docker コンテナを実行します。@Container と @DynamicPropertySource、または @ServiceConnection(Boot 3.1 以降)を使用します。シングルトンパターンでテスト間のコンテナを共有します。H2 では実現できない PostgreSQL 固有の機能をテストできます。
よくある質問
「Testcontainers:実データベースによる統合テスト」レッスンは無料ですか?
はい。「Testcontainers:実データベースによる統合テスト」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「Testcontainers:実データベースによる統合テスト」で何を学びますか?
TestcontainersでDocker上にPostgreSQLを起動し、実際のデータベースに対して統合テストを実行します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「Testcontainers:実データベースによる統合テスト」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- @CsvSourceと@MethodSourceによるパラメータ化テスト
- Mockito応用:ArgumentCaptorとスパイ
- Spring Bootテストスライス:@WebMvcTestと@DataJpaTest
- Testcontainers:実データベースによる統合テスト