18.07.2024

Разработка интеграционных тестов на Java с использованием Testcontainers

Интеграционные тесты проверяют взаимодействие компонентов системы, гарантируя их корректную совместную работу. Testcontainers упрощает их написание и повышает качество в Java, используя контейнеры Docker для запуска реальных зависимостей. В статье рассмотрим, как использовать библиотеку Testcontainers для написания интеграционных тестов в Java.

Что такое Интеграционные тесты?

Интеграционные тесты используются для проверки взаимодействия различных компонентов приложения, таких как базы данных, сторонние API и очереди сообщений. Цель - выявление ошибок, возникающих при работе компонентов вместе.
Отличие этого способа заключается в том, что он фокусируется на интерфейсах и потоке данных между модулями. При этом проверяется, как компоненты взаимодействуют друг с другом, а не отдельные функции каждого модуля.
Интеграционные тесты охватывают контроллеры, в то время как юнит-тесты занимаются алгоритмами и доменной моделью. Хотя интеграционное тестирование требует больше ресурсов, оно обеспечивает более надежную защиту от ошибок и устойчивость к изменениям.
Основные подходы к интеграционному тестированию включают явное определение границ доменной модели, уменьшение слоев в приложении и избавление от циклических зависимостей.

Использование Testcontainers для интеграционных тестов
Testcontainers - библиотека для тестирования, которая позволяет создавать и использовать контейнеры Docker в автоматизированных тестах. Предоставляет удобный способ запускать контейнеры для различных сервисов (например, базы данных, брокеры сообщений и другие) во время выполнения тестов.

Какие проблемы решает Testcontainers?

Позволяет создавать тесты, используя настоящие зависимости вместо заглушек, что обеспечивает более реалистичное тестирование.

Предоставляет гибкий API для создания необходимых зависимых сервисов в виде контейнеров Docker, что позволяет проводить интеграционные тесты с использованием реальных сервисов.

Изолирует тестовое окружение при запуске тестов, в отличие от использования виртуальных машин.

Использование Testcontainers позволяет избежать необходимости в заглушках при написании автотестов, обеспечивая надежное и реалистичное тестирование приложений, зависящих от внешних ресурсов.

Решает проблему совместимости, позволяя использовать специфичные для баз данных функции в ходе тестирования.

Гарантирует повторяемость тестов при запуске их как в CI, так и локально, независимо от количества тестируемых тестов.

Преимущества использования Testcontainers

1
Изолированная инфраструктура по требованию: не нужно заранее предоставлять инфраструктуру для интеграционного тестирования, Testcontainers запускает зависимые приложения перед началом тестов.
2
Последовательный опыт в локальной и CI-среде: можно запускать интеграционные тесты прямо из IDE, без отправки изменений и ожидания завершения CI.
3
Надежная настройка тестов с использованием стратегий ожидания: Testcontainers предлагает готовые стратегии ожидания для достижения полной инициализации контейнеров перед использованием.
4
Расширенные сетевые возможности: автоматическое сопоставление портов контейнера с доступными портами на хост-машинах, создание сетей Docker для связывания нескольких контейнеров.
5
Автоматическая очистка: Testcontainers автоматически удаляет созданные ресурсы после завершения теста с помощью контейнера-приставки Ryuk, обеспечивая надежную очистку даже при ненормальном завершении процесса тестирования.

Модули Testcontainers

Модули Testcontainers — предварительно настроенные реализации различных зависимостей, которые делают написание тестов еще проще. Основные модули Testcontainers включают в себя поддержку таких популярных технологий, как Kafka, Elasticsearch, MySQL, Redis и Selenium.
Модуль Kafka предоставляет удобный способ запуска брокера сообщений Kafka в контейнере для тестирования приложений, которые используют эту технологию для обмена данными.
Elasticsearch модуль обеспечивает возможность запуска поискового движка Elasticsearch в контейнере для тестирования приложений, связанных с процессами индексации и поиска данных.

Модуль MySQL позволяет запускать базу данных MySQL в контейнере для тестирования запросов и манипуляций данными.
Redis предоставляет возможность запуска кэширующего сервера Redis в контейнере для тестирования приложений, использующих кэширование данных.
Модуль Selenium помогает автоматизировать тестирование веб-приложений, запуская в тестовых сценариях браузеры в контейнерах.
Несмотря на широкий спектр модулей, предоставляемых Testcontainers, наша компания предпочитает использовать PostgresQL - модуль, который позволяет запускать базу данных PostgreSQL в контейнере для тестирования приложений, использующих эту реляционную СУБД.

PostgresQL - мощная и надежная база данных, широко применяемая в различных проектах и приложениях. Запуск PostgreSQL в контейнере с помощью Testcontainers делает тестирование и отладку приложений, использующих эту базу данных, более удобными и эффективными.

Этапы разработки интеграционных тестов на Java с применением Testcontainers

Testcontainers предоставляет удобный способ запуска контейнеров Docker в рамках тестовых сценариев на Java.
Для разработки интеграционных тестов на Java с использованием Testcontainers, необходимо выполнить следующие шаги:


1
Добавить зависимость Testcontainers в файл `pom.xml`:
```xml
<dependency>
<groupId>org.Testcontainers</groupId>
<artifactId>Testcontainers</artifactId>
<version>${Testcontainers.version}</version>
<scope>test</scope>
</dependency>
```


2
Написать тестовый класс, в котором будет происходить инициализация контейнеров и выполнение тестовых сценариев:
```java
import org.junit.jupiter.api.Test;
import org.Testcontainers.containers.MySQLContainer;
import org.Testcontainers.junit.jupiter.Container;
import org.Testcontainers.junit.jupiter.Testcontainers;
@Testcontainers
public class IntegrationTest {
@Container
public MySQLContainer mysql = new MySQLContainer();
@Test
public void testDatabaseConnection() {
// Подключение к MySQL контейнеру и выполнение запросов
}
}
```


3
Запустить интеграционные тесты с помощью сборщика Maven/Gradle или IDE.
Testcontainers позволяет легко настраивать и запускать контейнеры Docker для интеграционных тестов на Java, что делает процесс разработки и отладки более эффективным и надежным.

Примеры использования Testcontainers в реальных проектах Java

Для тестирования веб-приложений можно использовать модуль Testcontainers для Selenium. Он запускает браузеры в контейнерах и записывает видео выполнения тестов:

java
@Testcontainers
public class UserRepositoryTest {
@Container
private static PostgreSQLContainer<?> database = new PostgreSQLContainer<>("postgres:15.2")
.withDatabaseName("testdb")
.withUsername("testuser")
.withPassword("testpassword");
@Test
public void testFindByUsername() {
// Используем контейнер для взаимодействия с базой данных в тесте
String url = database.getJdbcUrl();
// ...
}
}

При разработке микросервисной архитектуры Testcontainers помогает создавать реалистичные тестовые окружения, запуская контейнеры с зависимыми сервисами. Например, можно поднять контейнеры с базой данных, брокером сообщений и тестируемым сервисом:

java
@Testcontainers
public class OrderServiceTest {
@Container
private static PostgreSQLContainer<?> database = new PostgreSQLContainer<>("postgres:15.2");
@Container
private static KafkaContainer kafka = new KafkaContainer("5.4.3");
@Test
public void testCreateOrder() {
// Используем контейнеры для тестирования взаимодействия сервисов
String dbUrl = database.getJdbcUrl();
String kafkaUrl = kafka.getBootstrapServers();
// ...
}
}

Testcontainers позволяет легко создавать контейнеры с базами данных для тестирования слоя доступа к данным. Например, можно использовать PostgreSQLContainer для тестирования кода, взаимодействующего с PostgreSQL:

java
@Testcontainers
public class UserRepositoryTest {
@Container
private static PostgreSQLContainer<?> database = new PostgreSQLContainer<>("postgres:15.2")
.withDatabaseName("testdb")
.withUsername("testuser")
.withPassword("testpassword");
@Test
public void testFindByUsername() {
// Используем контейнер для взаимодействия с базой данных в тесте
String url = database.getJdbcUrl();
// ...
}
}

Заключение

Использование Testcontainers в Java для интеграционного тестирования значительно улучшает качество и надежность тестов. Благодаря Docker-контейнерам упрощается создание реалистичных и изолированных тестовых сред. Testcontainers обеспечивает стабильное и воспроизводимое окружение независимо от локальной настройки, повышая уверенность в интеграции системы. Изолированная инфраструктура по требованию и автоматизированные процессы значительно сокращают время и усилия, необходимые для настройки и запуска интеграционных тестов.

Если Ваша компания нуждается в услугах автоматизированного тестирования для усиления ИТ-проектов, свяжитесь с нами, выбрав наиболее удобный способ.