ТестированиеТестирование API и интеграцийИнженер по интеграционному тестированию

Мок внешней зависимости подтверждает успешный ответ при каждом обращении и не фиксирует ожидаемую кратность...

Мок внешней зависимости подтверждает успешный ответ при каждом обращении и не фиксирует ожидаемую кратность вызова. Что такой тест может пропустить?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Такой тест может пропустить лишние или повторные обращения клиента к внешней зависимости. Если по контракту операция должна выполнять один вызов, мок должен проверять не только ответ, но и факт вызова, его параметры и допустимое число обращений.

Исторический контекст

Моки появились как способ изолировать тестируемый компонент от медленных, нестабильных или платных внешних систем. Изначально они помогали проверять логику клиента без запуска всей интеграционной цепочки.

Со временем стало очевидно, что проверка только возвращаемого ответа недостаточна. Взаимодействие с зависимостью имеет собственный контракт: важны метод, параметры, порядок и кратность вызовов.

Постановка проблемы

Клиент может случайно вызвать внешнюю систему дважды из-за повторного выполнения обработчика, ошибочного цикла, дублирования подписки или некорректной обработки ответа. Если мок одинаково успешно отвечает на каждый вызов и не считает обращения, тест завершится успешно.

Последствия зависят от операции. Для чтения это может привести к лишней нагрузке и задержке, для отправки уведомления — к дубликатам, для платежа или создания ресурса — к повторному побочному эффекту. Такой дефект способен проявиться только в интеграционной среде или в рабочей системе.

Подробное решение

Для операции, которая по контракту должна обращаться к зависимости один раз, тест должен проверять ровно один вызов. Обычно дополнительно фиксируют конкретный метод, адрес, существенные заголовки и тело запроса, чтобы тест подтверждал именно ожидаемое взаимодействие.

Если повторные вызовы предусмотрены контрактом, нельзя бездумно требовать ровно один вызов. Нужно проверять разрешённый сценарий: например, ограниченное число попыток, условия повтора и отсутствие повторной отправки после успешного ответа.

Проверка кратности — это тестовая гарантия поведения клиента, а не доказательство безопасности самой операции. Даже один вызов может завершиться повторным эффектом на стороне зависимости из-за сетевого сбоя после фактического выполнения. Поэтому для небезопасных повторов отдельно нужен контракт идемпотентности или другой механизм защиты операции.

Слишком строгая проверка всех технических деталей делает тест хрупким. Следует фиксировать только значимые для контракта свойства, а число вызовов выбирать из бизнес-сценария: один вызов для обычного запроса, допустимый диапазон или последовательность для политики повторов.

Ситуация из практики

Клиент отправляет запрос на создание уведомления. Из-за ошибки в обработчике один и тот же метод вызывается дважды, но тестовый мок возвращает успешный ответ на оба обращения. Тест проходит, хотя пользователь получает два уведомления.

Рассматривались два варианта. Можно было проверять только итоговое состояние в локальной базе, но это не выявляло лишний внешний вызов. Можно было требовать ровно один вызов без учёта сценариев временной ошибки, однако такая проверка конфликтовала бы с допустимой политикой повторов.

Выбрали проверку кратности отдельно для каждого сценария: один вызов при успешной первой попытке и ограниченная последовательность вызовов при временной ошибке. Дополнительно проверили, что после успешного ответа повтор не выполняется. В результате дефект дублирования обнаруживался на уровне теста клиента, а сценарий повторов оставался проверяемым и не был запрещён искусственно.

Что кандидаты часто упускают

1. Достаточно ли проверить, что зависимость была вызвана хотя бы один раз?

Нет. Проверка факта вызова не отличает один вызов от двух или десяти. Если для сценария важна кратность, тест должен явно проверять точное число либо допустимый диапазон вызовов.

2. Нужно ли всегда требовать ровно один вызов?

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

3. Гарантирует ли проверка одного вызова отсутствие дублирования побочного эффекта?

Нет. Она гарантирует только поведение тестируемого клиента в рамках наблюдаемого взаимодействия. Внешняя система могла обработать запрос, но клиент не получил ответ и отправил его снова в другом сценарии; защиту от такого случая обеспечивают идемпотентность, ключ операции или иной контракт внешней зависимости.