JavaテストのDockerテストコンテナ

1.はじめに

  • このチュートリアルでは、Javaの TestContainers ライブラリを見ていきます。** テストでDockerコンテナを使用することができます。その結果、外部リソースに依存する自己完結型の統合テストを書くことができます。

テストには、dockerイメージを持つ任意のリソースを使用できます。たとえば、データベース、Webブラウザ、Webサーバー、およびメッセージキューのイメージがあります。したがって、テスト内でそれらをコンテナとして実行できます。

2.要件

TestContainers ライブラリは、Java 8以降で使用できます。その上、それはJUnit Rules APIと互換性があります。

まず、コア機能に対するMavenの依存関係を定義しましょう。

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>testcontainers</artifactId>
    <version>1.8.0</version>
</dependency>

特殊コンテナ用のモジュールもあります。このチュートリアルでは、 _ PostgreSQL Seleniumを使用します。 _

関連する依存関係を追加しましょう。

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>postgresql </artifactId>
    <version>1.8.0</version>
</dependency>
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>selenium </artifactId>
    <version>1.8.0</version>
</dependency>

最新版はhttps://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.testcontainers%22%20AND%20a%3A%22testcontainers%22[Maven Central]でご覧になれます。

  • また、コンテナを実行するにはDockerが必要です** 。インストール方法についてはhttps://docs.docker.com/install/[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 image nameを指定して、 GenericContainer テストルールを作成します。それから、ビルダーメソッドでそれを設定します。

  • コンテナからポートを公開するために __withExposedPorts __を使います

  • withCommand はコンテナコマンドを定義します。それはいつ実行されます

コンテナが起動します。

このルールには __ @ ClassRuleという注釈が付けられています。その結果、そのクラスのテストが実行される前にDockerコンテナーが開始されます。 . __すべてのメソッドが実行された後でコンテナーは破棄されます。

@ Rule アノテーションを適用すると、 GenericContainer ruleはテストメソッドごとに新しいコンテナを開始します。そしてそのテストメソッドが終了したらコンテナを停止します。

  • コンテナ内で実行されているプロセスと通信するために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ライブラリの助けを借りて、コンテナ内でデータベースを実行することができます。

たとえば、PostgreSQLコンテナを PostgreSQLContainer ルールで起動します。それから、ヘルパーメソッドを使用することができます。

  • データベース接続用の 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 ruleは Chrome Firefox in docker-selenium __containersの実行を可能にします。

それから、 RemoteWebDriverでそれらを管理します。

これは、WebアプリケーションのUI/受け入れテストを自動化するのに非常に便利です。

@Rule
public BrowserWebDriverContainer chrome
  = new BrowserWebDriverContainer()
    .withDesiredCapabilities(DesiredCapabilities.chrome());

@Test
public void whenNavigatedToPage__thenHeadingIsInThePage() {
    RemoteWebDriver driver = chrome.getWebDriver();
    driver.get("https://saucelabs.com/test/guinea-pig");
    String heading = driver
      .findElement(By.xpath("/html/body/h1")).getText();

    assertEquals("This page is a Selenium sandbox", heading);
}

4.3. Docker Compose

テストにもっと複雑なサービスが必要な場合は、それらを 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__メソッドを使います

[source,java,gutter:,true]

@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 ____ruleを使いました。

それから、__PostgreSQLContainer、BrowserWebDriverContainer__、および__DockerComposeContainer__ルールを調べました。それらは特定のユースケースに対してより多くの機能を与えます。

最後に、ここにあるコードサンプルはhttps://github.com/eugenp/tutorials/tree/master/testing-modules/test-containers[GitHubに載っています]。
前の投稿:Javaで時間なしで日付を取得する
次の投稿:Spring Cache - カスタムKeyGeneratorの作成