README.md

Эксперименты с Тестконтейнерами

Описание

Основная цель - разобраться с возможными вариантами поднятия тестового окружения с помощью testcontainers или docker-compose.

Статья на Habr: https://habr.com/ru/articles/986870/

Дополнительные цели:

  • testcontainers: разобраться, как настраивать контейнеры на работу без перезапуска при ребилде приложения
  • devtools: разобраться, как пользоваться
  • создать примеры тестов, которые можно использовать для интеграционного тестирования

Приложение:

  • Spring Web
  • Spring Data JPA + для генерации идентификаторов воспользуемся TSID от Vlad Mihalcea https://vladmihalcea.com/uuid-database-primarykey
  • Postgresql
  • Кафку будем конфигурировать вручную, без использования Spring Kafka, для имитации необходимости подключаться к разным источникам
  • Для обращений по rest к сторонним сервисам создадим Spring-клиента через интерфейс HttpExchange
  • Для конвертации dto используем mapstruct
  • Для миграций используем liquibase

Что будем тестировать:

  • обработка входящего rest-запроса и сохранение результатов в БД
  • получение данных из БД по rest-запросу
  • отправка сообщения в Кафку
  • получение сообщения из Кафки
  • получение ответа от стороннего сервиса по rest

Что надо для интеграционного тестирования (реализовано в TestAppicationConfiguration):

  • Поднять постгрес
  • Поднять кафку. Если источников будет больше одного, то на каждый поднимем отдельный контейнер.
  • Поднять wiremock rest-сервер для имитации внешнего rest-сервиса. Если внешних сервисов будет больше, то на каждый поднимем отдельный контейнер.
  • Установка пропертей приложения на основе поднятых контейнеров: порты, url и так далее
  • Заполнение базы тестовыми данными
  • Создание базовых rest-моков, которые будут использоваться при старте тестового приложения
  • При необходимости создание топиков в Кафке
  • Для запросов к приложению используем RestAssured, чтобы имитировать полностью внешний запрос. При переходе на Spring Boot 4 можно будет выпилить и использовать штатные средства.
  • Для сравнения ожидаемых ответов приложения с актуальными будем сравнивать JSON, потому что так проще сохранять эталонные ответы

Что хотелось бы показать еще, но пока не реализовано: [ ] Добавление и зачистка тестовых данных в БД для конкретных тестов. Не используем @Transactional. [ ] Стаб для LocalDateTime [ ] Проверка содержимого логов в тестовых целях [ ] Подключение JaCoCo/SonarQube

Запуск

Gradle

Версии зависимостей gradle см. в gradle/libs.versions.toml

Сборка

./gradlew clean build --info

Запуск тестовой версии приложения с поднятием тестового окружения

./gradlew bootTestRun

Повторная сборка приложения при изменениях классов - devtools автоматически выполнит рестарт приложения

./gradlew build -x test

Maven

Сборка

./mvnw clean verify

Запуск тестовой версии приложения с поднятием тестового окружения

./mvnw spring-boot:test-run

Повторная сборка приложения при изменениях классов - devtools автоматически выполнит рестарт приложения

./mvnw compile

Эндпоинты для проверки

curl -X 'POST' 'http://localhost:8095/order/create' -H "Content-Type: application/json" -d '{"customerId": 123456,"items": [{"productId": 888,"quantity": 20, "amount":100.00}]}'
curl 'http://localhost:8095/order/list?customerId=654321'
curl 'http://localhost:8095/order/sum?customerId=654321'
curl -X 'POST' 'http://localhost:8095/payment/pay' -H "Content-Type: application/json" -H "X-Customer-Id: 123456" -d '{"amount":100.00}'

Матчасть

Варианты реализации

Spring way - через бины

  • @TestConfiguration
  • @Bean
  • @Import + @Autowired для контейнеров
  • @RestartScope чтобы не гасить контейнеры при ребилде

Через аннотации из Testcontainers -> Поднимаем контейнеры вручную

Вместо этой одной должно было быть две реализации - одна с использованием аннотаций @Testcontainers, а вторая - с ручным поднятием контейнеров. Но потом я перечитал статью The best way to use Testcontainers with Spring Boot (ссылка выше) и решил ограничиться одной реализацией - с ручным подъемом контейнеров. Тем более что эту реализацию я довольно долго использовал ранее.

docker-compose

Некоторой альтернативой использования Testcontainers для обеспечения приложения тестовым окружением может быть использование docker-compose. То есть просто поднимаем всю инфраструктуру приложения в Докере рядом. Это не позволит использовать тестовую инфраструктуру в тестах. Но просто поднять окружение, запустить приложение и подебажить его - вполне.

docker-compose см. в папке docker. Подробное описание, как и что делать - в файле ./docker/README.md

Дополнительно:

Обновление зависимостей

Gradle

Gradle Versions Plugin

./gradlew dependencyUpdates -Drevision=release -DoutputFormatter=html

Отчет ищи тут: ./build/dependencyUpdates/report.html

Maven

./mvnw versions:display-dependency-updates
./mvnw versions:display-plugin-updates
Конвейеры
0 успешных
0 с ошибкой