JavaテストのDockerテストコンテナ
1. 序章
このチュートリアルでは、JavaTestContainersライブラリを確認します。テスト内でDockerコンテナーを使用できるようにします。 その結果、外部リソースに依存する自己完結型の統合テストを作成できます。
Dockerイメージを持つテストでは、任意のリソースを使用できます。 たとえば、データベース、Webブラウザ、Webサーバー、およびメッセージキューの画像があります。 したがって、テスト内でそれらをコンテナとして実行できます。
2. 要件
TestContainersライブラリはJava8以降で使用できます。 また、JUnitルールAPIと互換性があります。
まず、コア機能のMaven依存関係を定義しましょう。
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.11.4</version>
</dependency>
専用コンテナ用のモジュールもあります。 このチュートリアルでは、 PostgreSQL と
関連する依存関係を追加しましょう:
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql </artifactId>
<version>1.11.4</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>selenium </artifactId>
<version>1.11.4</version>
</dependency>
最新バージョンはMavenCentralで見つけることができます。
また、コンテナーを実行するにはDockerが必要です。 インストール手順については、Dockerのドキュメントを参照してください。
テスト環境でDockerコンテナーを実行できることを確認してください。
3. 使用法
一般的なコンテナルールを設定しましょう。
@ClassRule
public static GenericContainer simpleWebServer
= new GenericContainer("alpine:3.2")
.withExposedPorts(80)
.withCommand("/bin/sh", "-c", "while true; do echo "
+ "\"HTTP/1.1 200 OK\n\nHello World!\" | nc -l -p 80; done");
Dockerイメージ名を指定して、GenericContainerテストルールを作成します。 次に、ビルダーメソッドを使用して構成します。
- withExposedPorts を使用して、コンテナーからポートを公開します
- withCommandはコンテナコマンドを定義します。 コンテナの起動時に実行されます。
ルールには注釈が付けられています
@Rule アノテーションを適用すると、GenericContainerルールはテストメソッドごとに新しいコンテナーを開始します。 そして、そのテストメソッドが終了するとコンテナを停止します。
IPアドレスとポートを使用して、コンテナで実行されているプロセスと通信できます:
@Test
public void givenSimpleWebServerContainer_whenGetReuqest_thenReturnsResponse()
throws Exception {
String address = "http://"
+ simpleWebServer.getContainerIpAddress()
+ ":" + simpleWebServer.getMappedPort(80);
String response = simpleGetRequest(address);
assertEquals(response, "Hello World!");
}
4. 使用モード
テストコンテナには、いくつかの使用モードがあります。 GenericContainerを実行する例を見ました。
TestContainers ライブラリには、特殊な機能を備えたルール定義もあります。 これらは、MySQL、PostgreSQLなどの一般的なデータベースのコンテナ用です。 およびWebクライアントのような他の人。
それらを汎用コンテナーとして実行できますが、特殊化により、拡張された便利なメソッドが提供されます。
4.1. データベース
データアクセス層統合テスト用のデータベースサーバーが必要であると仮定しましょう。 TestContainersライブラリを使用して、コンテナ内のデータベースを実行できます。
たとえば、PostgreSQLContainerルールを使用してPostgreSQLコンテナを起動します。 次に、ヘルパーメソッドを使用できるようになります。これらは、データベース接続用のgetJdbcUrl、getUsername、getPasswordです:
@Rule
public PostgreSQLContainer postgresContainer = new PostgreSQLContainer();
@Test
public void whenSelectQueryExecuted_thenResulstsReturned()
throws Exception {
String jdbcUrl = postgresContainer.getJdbcUrl();
String username = postgresContainer.getUsername();
String password = postgresContainer.getPassword();
Connection conn = DriverManager
.getConnection(jdbcUrl, username, password);
ResultSet resultSet =
conn.createStatement().executeQuery("SELECT 1");
resultSet.next();
int result = resultSet.getInt(1);
assertEquals(1, result);
}
PostgreSQLを汎用コンテナとして実行することも可能です。 ただし、接続を構成するのはさらに困難です。
4.2. Webドライバー
もう1つの便利なシナリオは、Webブラウザーでコンテナーを実行することです。 BrowserWebDriverContainer ルールは、docker-seleniumコンテナーでChromeおよびFirefoxを実行できるようにします。 次に、それらを管理します
これは、WebアプリケーションのUI/受け入れテストを自動化するのに非常に役立ちます。
@Rule
public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer()
.withCapabilities(new ChromeOptions());
@Test
public void whenNavigatedToPage_thenHeadingIsInThePage() {
RemoteWebDriver driver = chrome.getWebDriver();
driver.get("http://example.com");
String heading = driver.findElement(By.xpath("/html/body/div/h1"))
.getText();
assertEquals("Example Domain", heading);
}
4.3. DockerCompose
テストでより複雑なサービスが必要な場合は、docker-composeファイルで指定できます。
simpleWebServer:
image: alpine:3.2
command: ["/bin/sh", "-c", "while true; do echo 'HTTP/1.1 200 OK\n\nHello World!' | nc -l -p 80; done"]
次に、DockerComposeContainerルールを使用します。 このルールは、作成ファイルで定義されているとおりにサービスを開始および実行します。
getServiceHostおよびgetServicePostメソッドを使用して、サービスへの接続アドレスを作成します。
@ClassRule
public static DockerComposeContainer compose =
new DockerComposeContainer(
new File("src/test/resources/test-compose.yml"))
.withExposedService("simpleWebServer_1", 80);
@Test
public void givenSimpleWebServerContainer_whenGetReuqest_thenReturnsResponse()
throws Exception {
String address = "http://" + compose.getServiceHost("simpleWebServer_1", 80) + ":" + compose.getServicePort("simpleWebServer_1", 80);
String response = simpleGetRequest(address);
assertEquals(response, "Hello World");
}
5. 結論
TestContainersライブラリの使用方法を確認しました。 統合テストの開発と実行が容易になります。
特定のDockerイメージのコンテナーには、GenericContainerルールを使用しました。 次に、 PostgreSQLContainer、BrowserWebDriverContainer 、およびDockerComposeContainerのルールを確認しました。 これらは、特定のユースケースに対してより多くの機能を提供します。
最後に、ここのコードサンプルはGitHubのにあります。