Как тестировать микросервисы?

«Как тестировать микросервисы?» — вопрос из категории Архитектура, который задают на 38% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Тестирование микросервисной архитектуры требует комбинации стратегий, чтобы покрыть изолированную логику и сложное межсервисное взаимодействие.

1. Модульное тестирование (Unit Testing): Проверяем бизнес-логику внутри одного сервиса в изоляции, используя моки для всех внешних зависимостей (база данных, другие сервисы).

// Пример (JUnit + Mockito для сервиса на Java)
@Test
void calculateOrderTotal_ShouldApplyDiscount() {
    // Arrange
    ItemRepository mockRepo = mock(ItemRepository.class);
    when(mockRepo.findPrice("item1")).thenReturn(100.0);
    OrderService service = new OrderService(mockRepo);
    // Act & Assert
    assertEquals(90.0, service.calculateTotal(Arrays.asList("item1")), 0.01);
}

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

3. Контрактное тестирование (Contract Testing): Критически важный уровень. Инструменты вроде Pact позволяют проверить, что потребитель и поставщик сервиса соблюдают согласованный контракт (формат запроса/ответа), не разворачивая всю систему. Это предотвращает поломки при деплое.

4. Тестирование взаимодействия сервисов (Component/Service Testing): Запускаем тестируемый сервис со всеми его зависимостями (заглушками или реальными) и проверяем его API end-to-end, но в пределах его границ.

5. Сквозное тестирование (End-to-End): Моделируем ключевые пользовательские сценарии, проходящие через несколько сервисов. Таких тестов должно быть немного из-за их хрупкости, сложности поддержки и долгого выполнения. Используются инструменты типа Cypress, Selenium или Karate.

6. Нефункциональное тестирование:

  • Нагрузочное/стресс-тестирование: Проверяем, как система ведет себя под нагрузкой (например, с помощью k6 или Gatling), особенно важно для выявления узких мест в межсервисной коммуникации.
  • Тестирование отказоустойчивости (Resilience): Проверяем механизмы вроде Circuit Breaker, повторных попыток (retry), откатов (fallback). Инструменты: Chaos Monkey, Istio для инжекции задержек и ошибок.

Практический подход: Строим "пирамиду тестов", где много быстрых и стабильных модульных и контрактных тестов, меньше интеграционных и совсем мало E2E-тестов. Вся эта цепочка автоматизирована в CI/CD (например, GitLab CI, Jenkins).