MPのご利用は計画的に

だいたい自分用のメモ

Kotlinでtestcontainers-javaをつかう

概要

Testcontainersってなに?

プログラムからDockerコンテナを起動できるライブラリ 最近testcontainers-javaとJUnit5のjupiterへの親和性が高くなったらしいので試したメモです。

環境

  • Kotlin 1.3.10
  • JUnit-jupiter 5.3.1
  • Testcontainers-java 1.10.1

どうする

pomに依存を足す

依存にはTestcontainersとJUnit5と、ドキュメントにはでてきていないような気がするけど、 Testontainersが作っているJUnit5用のExtensionが必要です 今回はPostgreSQLのコンテナを試してみるのでPostgreSQL用の依存も追加します。

<!-- pom抜粋 -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>${junit.jupiter.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>testcontainers</artifactId>
    <version>${testcontainers.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>${testcontainers.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>postgresql</artifactId>
    <version>${testcontainers.version}</version>
    <scope>test</scope>
</dependency>

テストクラスを作る

クラスに@Testcontainersアノテーションをつけて、PostgreSQLContainerというクラスのインスタンスを作ってあげるだけでOK。 クラス変数として作成するとテストクラスのインスタンス生成時にDBが起動して、テストが全て終わったら停止します。 インスタンス変数にすると各テストメソッドごとに起動と停止が実行されます。

インスタンス生成時にデータベース名やUsername/Passwordも一緒に設定できます。

@Suppress("NonAsciiCharacters", "TestFunctionName")
@Testcontainers
class SampleTestContainer {

    companion object {
        @Container
        private val container = PostgreSQLCotainer()
                .withDatabaseName("postgres")
                .withUsername("postgres")
                .withPassword("")
    }

    @Test
    fun コンテナが起動している() {
        assertTrue(container.isRunning)
    }
}

と思ったら

SELF-TypeReferenceが使われてて、今のKotlinだとそのままインスタンス化はできない?らしいので、 継承したクラスを作ってお茶を濁すことに。。(この辺あまり詳しくないです

class PostgreSQLKotainer : PostgreSQLContainer<PostgreSQLKotainer>()

// ... 抜粋 ...
@Container
private val container = PostgreSQLKotainer()
// ...........

気をつけること

Dockerなのでどうしても起動に待ち時間が必要になります。 1回だけ実行するならそんなに気にならないけど、開発時に何回も実行するとなるとツライ。 テストを実行する前に起動して、テスト実行中はTRUNCATEDROPを使いつつ、すべてのテストが終わったら停止するような使い方が良さそうに感じました。