Внешний сервис в интеграционном тесте заменён моком, который всегда отвечает успешно. Как проверить, что клиент корректно обрабатывает временную недоступность зависимости?
Нужно настроить мок на воспроизведение временной недоступности: тайм-аут, сетевой сбой или временную ошибку внешнего сервиса. Тест должен проверить не только итоговый результат, но и ограниченное число повторов, соблюдение общего дедлайна и корректную финальную ошибку клиента.
Моки появились как способ изолировать тестируемый компонент от нестабильных, медленных или дорогих внешних зависимостей. Это делает проверки быстрыми и воспроизводимыми, но обычный мок часто моделирует только успешный ответ.
Такой подход хорошо проверяет обработку штатного сценария, однако скрывает ошибки устойчивости. В результате клиент может выглядеть исправным в тестах, но зависать, бесконечно повторять запросы или неправильно сообщать об отказе в рабочей среде.
Внешняя зависимость может быть временно недоступна из-за сетевого сбоя, превышения времени ожидания или кратковременной серверной ошибки. Если мок всегда возвращает успешный ответ, интеграционный тест не проверяет поведение клиента в этих условиях.
Риск зависит от роли операции. Для чтения повтор обычно безопаснее, чем для команды, создающей или изменяющей данные. Поэтому проверка должна учитывать не только факт повтора, но и допустимость повторной отправки конкретного запроса.
Мок должен поддерживать управляемые сценарии отказа: например, задержать ответ сверх тайм-аута, разорвать соединение или вернуть временную ошибку. Сценарий должен быть детерминированным: тест заранее задаёт, на каких попытках возникает сбой и когда зависимость становится доступной.
Проверка обычно включает четыре свойства:
Важно проверять наблюдаемое поведение клиента, а не внутренний вызов конкретной функции мока. Например, количество обращений можно контролировать через журнал запросов или счётчик мок-сервера, но сам тест должен оставаться независимым от реализации клиента.
Не следует считать любой отказ основанием для повтора. Постоянная ошибка запроса, ошибка авторизации или нарушение контракта обычно не исправляются повторной отправкой. Кроме того, сетевой тайм-аут не доказывает, что сервер не выполнил операцию: для изменяющих запросов повтор может привести к двойному эффекту, если операция не защищена идемпотентностью или другим механизмом дедупликации.
Тестовый мок не обязан полностью имитировать реальную сеть. Его задача — воспроизвести существенный для контракта отказ и дать проверяемый результат. Более реалистичные сетевые сбои можно дополнительно проверять на отдельном уровне, но они не должны быть единственным способом тестирования политики клиента.
Клиент обращался к сервису расчёта доставки. В обычных интеграционных тестах мок немедленно возвращал успешный тариф, поэтому тесты проходили даже после изменения политики повторов: клиент стал повторять запрос без ограничения при зависшем соединении.
Рассматривались три варианта. Запускать настоящий сервис было недостаточно воспроизводимо и дорого. Проверять только unit-уровень было быстро, но не подтверждало корректную настройку HTTP-клиента. Добавить в мок сценарий с тайм-аутом и восстановлением зависимости было немного сложнее, зато это проверяло поведение всей интеграционной цепочки.
Выбрали третий вариант: мок не отвечал на первой попытке, затем возвращал успешный результат. Тест проверял число запросов, ограничение времени ожидания и итоговый тариф. Отдельный сценарий подтверждал отказ после исчерпания лимита повторов; это выявило бесконечный retry-цикл до его попадания в рабочую среду.
Нет. Одинаковое число попыток может сопровождаться неправильными тайм-аутами и нарушением общего дедлайна. Нужно проверить временные границы поведения: клиент не должен ждать дольше согласованного срока, а сумма тайм-аутов отдельных попыток не должна незаметно превышать допустимое время операции.
Мок должен моделировать разные классы отказов, а тест — проверять различающуюся реакцию клиента. Временный сетевой сбой может допускать ограниченный повтор, тогда как ошибка авторизации или некорректный запрос должна завершаться сразу. Иначе тест подтвердит лишь наличие механизма повторов, но не корректность его условий.
При тайм-ауте клиент не знает, успел ли внешний сервис выполнить первый запрос. Если операция изменяет состояние, повтор может создать второй объект или повторно применить действие. Поэтому интеграционная проверка должна либо использовать безопасную для повторов операцию, либо подтверждать наличие в контракте идемпотентности, дедупликации или иного способа исключить двойной эффект.