Докер тестови контейнери в Java тестове

1. Въведение

В този урок ще разгледаме библиотеката Java TestContainers . Позволява ни да използваме контейнери на Docker в рамките на нашите тестове. В резултат на това можем да напишем самостоятелни тестове за интеграция, които зависят от външни ресурси.

В нашите тестове можем да използваме всеки ресурс, който има образ на докер. Например има изображения за бази данни, уеб браузъри, уеб сървъри и опашки за съобщения. Следователно можем да ги пуснем като контейнери в рамките на нашите тестове.

2. Изисквания

Библиотеката TestContainers може да се използва с Java 8 и по-нова версия . Освен това е съвместим с JUnit Rules API.

Първо, нека дефинираме зависимостта maven за основната функционалност:

 org.testcontainers testcontainers 1.11.4 

Има и модули за специализирани контейнери. В този урок ще използваме PostgreSQL и Selenium.

Нека добавим съответните зависимости:

 org.testcontainers postgresql  1.11.4   org.testcontainers selenium  1.11.4 

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

Освен това се нуждаем от 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");

Изграждаме тестово правило GenericContainer, като указваме име на изображение на докер. След това го конфигурираме със строителни методи:

  • Използваме withExposedPorts, за да изложим порт от контейнера
  • withCommand дефинира команда за контейнер. Той ще бъде изпълнен, когато контейнерът стартира.

Правилото е коментирано с @ClassRule. В резултат на това той ще стартира контейнера на Docker, преди да се изпълни какъвто и да е тест в този клас . Контейнерът ще бъде унищожен след изпълнението на всички методи.

Ако приложите @Rule анотация, GenericContainer правило ще започне нов контейнер за всеки метод на изпитване. И ще спре контейнера, когато този метод за изпитване приключи.

Можем да използваме IP адрес и порт, за да комуникираме с процеса, който се изпълнява в контейнера :

@Test public void givenSimpleWebServerContainer_whenGetReuqest_thenReturnsResponse() throws Exception { String address = "//" + simpleWebServer.getContainerIpAddress() + ":" + simpleWebServer.getMappedPort(80); String response = simpleGetRequest(address); assertEquals(response, "Hello World!"); }

4. Режими на използване

Има няколко режима на използване на тестовите контейнери. Видяхме пример за стартиране на GenericContainer.

Библиотеката TestContainers също има дефиниции на правила със специализирана функционалност. Те са за контейнери на често срещани бази данни като MySQL, PostgreSQL; и други като уеб клиенти.

Въпреки че можем да ги изпълняваме като общи контейнери, специализациите предоставят разширени методи за удобство.

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. Уеб драйвери

Друг полезен сценарий е да стартирате контейнери с уеб браузъри. Правилото BrowserWebDriverContainer позволява стартирането на Chrome и Firefox в докер-селенови контейнери. След това ги управляваме с RemoteWebDriver.

Това е много полезно за автоматизиране на тестове за потребителски интерфейс / приемане за уеб приложения:

@Rule public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer() .withCapabilities(new ChromeOptions()); @Test public void whenNavigatedToPage_thenHeadingIsInThePage() { RemoteWebDriver driver = chrome.getWebDriver(); driver.get("//example.com"); String heading = driver.findElement(By.xpath("/html/body/div/h1")) .getText(); assertEquals("Example Domain", heading); }

4.3. 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 = "//" + compose.getServiceHost("simpleWebServer_1", 80) + ":" + compose.getServicePort("simpleWebServer_1", 80); String response = simpleGetRequest(address); assertEquals(response, "Hello World"); }

5. Заключение

Видяхме как можем да използваме библиотеката TestContainers . Улеснява разработването и провеждането на тестове за интеграция.

Използвахме правилото GenericContainer за контейнери с дадени изображения на докер. След това разгледахме правилата на PostgreSQLContainer, BrowserWebDriverContainer и DockerComposeContainer . Те дават повече функционалност за конкретни случаи на употреба.

И накрая, примерни кодове тук могат да бъдат намерени в GitHub.