**Кейс 1: Стабирование внешнего платежного шлюза.** Представьте сервис обработки платежей, который взаимодействует с внешним провайдером (например, Stripe или PayPal). Прямые вызовы в тестах невозможны: они требуют реальных ключей, списывают деньги и нестабильны. Наивный подход — хардкодить успешный ответ в классе-заглушке. Лайфхак: используйте библиотеку **WireMock** как standalone-сервер или встроенный (embedded) режим. Она позволяет не только возвращать статичные ответы, но и:
* Проверять, что ваше приложение отправляет корректные заголовки и тело запроса (верификация).
* Задавать динамические ответы на основе параметров запроса с помощью Response Templating.
* Имитировать сетевые ошибки (таймауты, 5xx статусы) для тестирования resilience-логики вашего приложения.
* Сохранять все запросы-ответы в snapshot-файлы для отладки.
Настройка WireMock в Spring-тесте с аннотацией @AutoConfigureWireMock позволяет заменить реальный URL платежного шлюза на localhost в тестовом контексте.
**Кейс 2: Имитация сервиса уведомлений с состоянием.** Допустим, ваш сервис отправляет уведомления через внешний EmailService и должен проверять статус доставки. Стаб должен не просто отвечать «OK», а вести себя как реальный сервис с памятью. Решение: создайте стаб в виде in-memory реализации интерфейса, которая хранит отправленные уведомления в коллекции (например, ConcurrentHashMap). В тестах вы сможете затем проверить, что уведомление с нужными параметрами было «отправлено». Более сложный вариант — реализовать простую очередь внутри стаба, чтобы имитировать задержку доставки и позволить тесту асинхронно запросить статус.
**Кейс 3: Стабирование сложного GraphQL или gRPC API.** Для REST WireMock подходит идеально, но для GraphQL или gRPC нужны иные подходы. Для GraphQL отличным решением является **GraphQL Mock** или использование библиотеки graphql-java для создания in-memory схемы, которая возвращает предопределенные данные. Ключевой лайфхак: выносите стабы GraphQL в отдельные .graphqls-файлы с расширениями (directives) для указания мок-данных или используйте инструменты вроде Apollo Server (для TypeScript) в тестовом режиме. Для gRPC можно использовать **grpc-java** тестовый фреймворк и InProcessServer, который запускает сервер в памяти, или создавать моки реализаций интерфейсов сервисов с помощью Mockito.
**Кейс 4: Лайфхак для конфигурации и данных.** Часто стабы требуют конфигурации (URL, таймауты). Не хардкодьте их в тестах. Используйте Spring-профили или свойства. Создайте файл `application-test.yml`, где укажите `external.service.url: http://localhost:${wiremock.server.port}`. Это делает конфигурацию чистой и централизованной. Для данных используйте паттерн «Test Data Builder» или библиотеку типа **Java Faker** для генерации правдоподобных, но случайных данных в стабах, что делает тесты более устойчивыми и менее хрупкими.
**Кейс 5: Стабы для асинхронных и событийно-ориентированных взаимодействий.** Если ваш сервис публикует события в Kafka или RabbitMQ и ожидает ответа в другой очереди, стабы должны эмулировать и это. Используйте **Embedded Kafka** или **Testcontainers** с образами Kafka/RabbitMQ для поднятия реального брокера в тестах. Это тяжеловеснее, но максимально приближено к продакшену. Альтернатива — создание простого заглушечного `KafkaTemplate` или `RabbitTemplate`, который перехватывает сообщения и складывает их в блокирующую очередь, из которой тест может их прочитать и ассертить.
**Общие лайфхаки для всех кейсов:**
- **Именование:** Давайте стабам понятные имена, отражающие их роль (например, `AlwaysSuccessfulPaymentGatewayStub`, `FailingEmailServiceStub`).
- **Переиспользование и библиотеки:** Не копируйте код стабов между проектами. Выносите общие стабы внешних сервисов в отдельный тестовый jar-модуль или библиотеку.
- **Верификация взаимодействий:** Всегда проверяйте, что ваш код корректно взаимодействует со стабом: вызвал нужный метод с правильными аргументами, определенное количество раз. Mockito.verify() — ваш друг.
- **Документация стабов:** В коде стаба кратко документируйте, какое поведение он имитирует и для каких сценариев предназначен.
- **Очистка состояния:** Убедитесь, что состояние стаба сбрасывается между тестами (@Before или @After метод), чтобы тесты были изолированными и идемпотентными.
Комментарии (12)