Контейнеры Docker в тестах Java

Тестовые контейнеры Docker в тестах Java

1. Вступление

In this tutorial, we’ll be looking at Java TestContainers library. Это позволяет нам использовать контейнеры Docker в наших тестах. В результате мы можем написать автономные интеграционные тесты, которые зависят от внешних ресурсов.

В наших тестах мы можем использовать любой ресурс с изображением докера. Например, существуют изображения для баз данных, веб-браузеров, веб-серверов и очередей сообщений. Поэтому мы можем запускать их как контейнеры в наших тестах.

2. Требования

БиблиотекуTestContainers можно использовать с Java 8 и выше. Кроме того, он совместим с API правил JUnit.

Во-первых, давайте определим зависимость maven для основных функций:


    org.testcontainers
    testcontainers
    1.11.4

Есть также модули для специализированных контейнеров. В этом руководстве мы будем использоватьPostgreSQL andSelenium. 

Давайте добавим соответствующие зависимости:


    org.testcontainers
    postgresql 
    1.11.4


    org.testcontainers
    selenium 
    1.11.4

Мы можем найти последние версии наMaven Central.

Also, we need Docker to run containers. Обратитесь кDocker documentation за инструкциями по установке.

Убедитесь, что у вас есть возможность запускать контейнеры 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");

Мы создаем тестовое правилоGenericContainer, указав имя образа докера. Затем мы настраиваем его с помощью методов компоновщика:

  • Мы используемwithExposedPorts to, чтобы открыть порт из контейнера

  • withCommand определяет команду контейнера. Это будет выполнено, когда контейнер запустится.

Правило помечено@ClassRule. . В результате оно запустит контейнер Docker до того, как запустится любой тест в этом классе... Контейнер будет уничтожен после выполнения всех методов.

Если вы примените аннотацию@Rule, правилоGenericContainer запустит новый контейнер для каждого метода тестирования. И он остановит контейнер, когда этот метод тестирования завершится.

We can use IP address and port to communicate with the process running in the container:

@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. Режимы использования

Тестовых контейнеров несколькоusage modes. Мы видели пример запускаGenericContainer.

БиблиотекаTestContainers также содержит определения правил со специализированной функциональностью. Они предназначены для контейнеров общих баз данных, таких как MySQL, PostgreSQL; и другие, как веб-клиенты.

Хотя мы можем запускать их как универсальные контейнеры, специализации предоставляют расширенные удобные методы.

4.1. Базы данных

Предположим, нам нужен сервер базы данных для тестов интеграции уровня доступа к данным. Мы можем запускать базы данных в контейнерах с помощью библиотеки TestContainers.

Например, мы запускаем контейнер PostgreSQL с правиломPostgreSQLContainer. Затем мы можем использовать вспомогательные методы. These are getJdbcUrl, getUsername, getPassword for database connection:

@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. Веб-драйверы

Еще один полезный сценарий - запуск контейнеров с помощью веб-браузеров. ПравилоBrowserWebDriverContainer позволяет запускать сконтейнерыChrome andFirefox indocker-selenium . Затем мы управляем ими с помощьюRemoteWebDriver. 

Это очень полезно для автоматизации 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. 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. Это правило запускает и запускает службы, как определено в файле compose.

Мы используем методы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. Это облегчает разработку и запуск интеграционных тестов.

Мы использовали правилоGenericContainer для контейнеров заданных образов докеров. Затем мы рассмотрели правилаPostgreSQLContainer, BrowserWebDriverContainer иDockerComposeContainer. Они дают больше функциональности для конкретных случаев использования.

Наконец, здесь можно найти примеры кодаover on GitHub.

Related