Когда речь идет о тестировании Spring-приложений, нам часто приходится решать, как эмулировать реальные компоненты и внешние сервисы, чтобы тесты были как можно более похожи на реальную работу приложения. Но вот где всё становится интересным: мы будем использовать Testcontainers для эмуляции наших зависимостей и контейнеров. И это будет весело! Приготовьтесь познакомиться с котиками, слонами и китами, которые помогут вам на пути к стабильным и качественным тестам!
Что такое Testcontainers и зачем нам котики, слоны и киты?
Testcontainers — это библиотека для Java, которая позволяет запускать Docker-контейнеры прямо в процессе тестирования. Вместо того чтобы подключаться к реальным базам данных или сервисам, Testcontainers запускает их в контейнерах, предоставляя вам возможность легко тестировать приложение с реальными зависимостями, не загромождая вашу среду.
Котики 🐱 — это, конечно же, ваше приложение, которое мы тестируем.
Слоны 🐘 — это ваша база данных PostgreSQL, которую мы будем эмулировать в контейнере.
Киты 🐋 — это Docker, который управляет всеми контейнерами и помогает нашему приложению взаимодействовать с ними.
Testcontainers — это инструмент, который помогает запускать временные контейнеры для тестов. С его помощью мы можем использовать контейнеры с базой данных или другими сервисами, чтобы протестировать наше приложение.
Почему Docker нам нужен?
Docker позволяет создать временную базу данных, не занимая много места на компьютере.
Testcontainers автоматически запустит нужную нам базу данных для тестов, а после тестов удалит её.
Вместо того чтобы вручную настраивать PostgreSQL, мы просто говорим Testcontainers: "Запусти контейнер с PostgreSQL", и всё готово!
Важно: Чтобы все это работало, у тебя должен быть установлен Docker. Без него контейнеры не смогут работать.
Установка Docker (если у тебя его нет)
Скачай и установи Docker Desktop с официального сайта.
Запусти Docker.
Настройка окружения с котиками и слонами
Для начала давайте настроим PostgreSQL (слона) с помощью Testcontainers. Представьте, что котик сидит за компьютером и готовится к работе, а слон подготавливает базу данных для тестов.
В нашем проекте нам нужны следующие зависимости:
<dependencies>
<!-- Testcontainers для Docker -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring Boot Starter Web для работы с контроллерами -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- PostgreSQL Driver -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- Spring Boot Test для тестирования -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Мы создадим контроллер, который будет управлять запросами к базе данных. Например, пусть это будет контроллер, который работает с сущностью Kitten , и при этом взаимодействует с базой данных PostgreSQL.
Пример контроллера:
@RestController
@RequestMapping("/kittens")
public class KittenController {
private final KittenService kittenService;
@Autowired
public KittenController(KittenService kittenService) {
this.kittenService = kittenService;
}
@GetMapping
public List<Kitten> getKittens() {
return kittenService.getAllKittens();
}
@PostMapping
public Kitten addKitten(@RequestBody Kitten kitten) {
return kittenService.addKitten(kitten);
}
}
Как видите, контроллер использует сервис KittenService, который, в свою очередь, обращается к репозиторию для получения и сохранения данных. А теперь давайте проверим, как все это работает, настроив окружение с Testcontainers.
Использование Testcontainers для запуска PostgreSQL
Чтобы эмулировать PostgreSQL в контейнере, нам нужно создать контейнер с PostgreSQL и указать его параметры для использования в тестах. Вместо того чтобы подключаться к реальной базе данных, мы запустим ее прямо в Docker-контейнере.
@Testcontainers
public class KittenControllerTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:14")
.withDatabaseName("test_db")
.withUsername("test")
.withPassword("test");
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@BeforeAll
public static void beforeAll() {
postgres.start(); //стартуем контейнер с Postgres
}
@Autowired
private TestRestTemplate restTemplate;
@Test
void testGetKittens() {
// Тестируем GET-запрос на получение котиков
ResponseEntity<List<Kitten>> response = restTemplate.exchange("/kittens", HttpMethod.GET, null,
new ParameterizedTypeReference<List<Kitten>>() {});
assertEquals(HttpStatus.OK, response.getStatusCode());
assertTrue(response.getBody().size() > 0);
}
@Test
void testAddKitten() {
// Тестируем POST-запрос на добавление нового котика
Kitten newKitten = new Kitten("Fluffy", 1);
ResponseEntity<Kitten> response = restTemplate.postForEntity("/kittens", newKitten, Kitten.class);
assertEquals(HttpStatus.CREATED, response.getStatusCode());
assertNotNull(response.getBody().getId());
}
}
Что происходит?
@Container
: Аннотация от Testcontainers, которая говорит, что postgres — это контейнер, который нужно запустить перед тестами.
PostgreSQLContainer<?>
: Специальный класс для создания контейнера PostgreSQL.
"postgres:14"
: Используем образ PostgreSQL версии 14.
withDatabaseName("test_db")
: Создаем базу данных с именем test_db.
withUsername("test")
и withPassword("test")
: Указываем логин и пароль для подключения к базе данных.
Таким образом, этот код создает контейнер PostgreSQL, который автоматически запускается перед тестами и завершает работу после их окончания. Это исключает необходимость устанавливать PostgreSQL вручную.
Аннотация @DynamicPropertySource
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
Аннотация @DynamicPropertySource
, которая позволяет динамически задавать свойства приложения во время тестов.
DynamicPropertyRegistry registry
: Хранилище для свойств, которое обновляется значениями из контейнера.
Зачем это нужно? Spring Boot-приложения используют application.properties
для настройки подключения к базе данных. Вместо того чтобы прописывать их вручную, мы берем данные из контейнера:
spring.datasource.url
: Получаем URL подключения к базе данных из контейнера.
spring.datasource.username
и spring.datasource.password
: Используем логин и пароль контейнера PostgreSQL.
Таким образом, приложение во время тестов подключается к базе данных в контейнере, а не к реальной базе данных. Это позволяет тестировать приложение в чистом изолированном окружении.
Как котики и слоны дружат с китами
Docker (кит) помогает нашему приложению Spring Boot запускать контейнеры с PostgreSQL (слон) для тестирования. Все это происходит благодаря Testcontainers, который автоматически запускает контейнеры и делает их доступными для вашего теста.
Когда вы запускаете тесты, Testcontainers подготавливает PostgreSQL контейнер с правильными настройками, а ваше приложение (котик) может без проблем взаимодействовать с ним. В этом процессе Docker (кит) берет на себя управление контейнерами и гарантирует, что все работает корректно.
Преимущества использования Testcontainers
Изоляция тестов. Каждый тест запускает новый контейнер, что позволяет гарантировать чистоту данных и изоляцию.
Реальные данные. Вы тестируете ваше приложение на реальных сервисах и базах данных, а не на мокаемых компонентах.
Легкость в настройке. Не нужно вручную устанавливать и конфигурировать базы данных — все автоматически настраивается в контейнерах.
Заключение: Как котики, слоны и киты помогли нам
В итоге, когда котики (Spring Boot приложение), слоны (PostgreSQL) и киты (Docker) объединяются в одном тесте, мы получаем мощную комбинацию для тестирования реальных зависимостей. Вы больше не зависите от локальных баз данных или мока, а можете быть уверены, что ваше приложение будет работать с настоящими сервисами и базами данных. Это и есть секрет успеха качественных тестов в современных Spring-приложениях!
Теперь у нас есть полностью настроенное тестирование с Testcontainers, и все работает как часы, благодаря котикам, слонам и китам! 🐱🐘🐋
Top comments (0)