Протестировать ретраи и бэкофф

Мок, который сперва падает, потом отвечает успехом — чтобы проверить логику ретраев.

Код ретраев тяжело тестировать, потому что настоящие API редко падают тогда, когда вам это нужно. Мок с последовательностью ответов это чинит: первый вызов отдаёт 500, следующий — 200, и цикл повторяется. Так вы получаете детерминированный отказ, на который может опереться тест, и можете доказать, что повтор действительно случился и вторая попытка прошла, а не просто предположить это.

Как заставить вызов упасть один раз и затем пройти?

Опишите ответ по умолчанию как отказ, а то, что идёт после него, — через последовательность ответов. Мок проходит её по шагу на вызов и затем начинает заново, поэтому один эндпоинт даёт схему «упал, потом прошёл», нужную любому тесту ретраев, — в фиксированном порядке и без случайности, которая делает тест плавающим.

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

Как проверить именно back-off, а не только число попыток?

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

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

Какие отказы вообще стоит повторять?

Повторять всё так же неправильно, как не повторять ничего. 500 или 503 стоят ещё одной попытки; 400 или 422 будут падать одинаково всегда, и ретрай лишь размножит ошибку. 429 — отдельный случай: тут надо соблюдать заголовок Retry-After, а не применять собственное расписание.

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

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

Что обычно идёт не так?

  • Повторяют неидемпотентные запросы. Повторённый POST может списать деньги дважды. Повторяйте только там, где дубль безвреден, либо используйте ключ идемпотентности.
  • Нет потолка. Ретраи без ограничения превращают короткий чужой сбой в ваш собственный длинный.
  • Ретрай без таймаута. Если первая попытка никогда не вернётся, повтор никогда не запустится — тестируйте зависание, а не только отказ.
  • Синхронные ретраи. Без джиттера все клиенты повторяют в один такт, и по восстанавливающемуся сервису бьёт сразу весь парк.

Когда это нужно

Логику ретраев почти никогда не тестируют — настоящий API не падает по команде. Этот мок отдаёт 500 на первый вызов и 200 на второй, затем повторяет, и автотест может проверить, что клиент ретраит и восстанавливается. Заголовок X-Mockapi-Variant показывает, какой шаг обслужил вызов.

Создать мок

curl -X POST https://quickmock.dev/api/mocks \
  -H 'Content-Type: application/json' \
  -d '{
  "method": "GET",
  "response_status": 500,
  "content_type": "application/json",
  "response_body": "{\"error\":\"upstream\"}",
  "response_sequence": [
    { "status": 200, "body": "{\"ok\":true}" }
  ]
}'

Вызвать

curl https://quickmock.dev/m/<slug>

Что получите

1st call  -> 500  (X-Mockapi-Variant: seq-1/2)
2nd call  -> 200  (seq-2/2)
...then it cycles

Частые вопросы

Порядок отказов детерминирован?
Да. Последовательность ответов проходится по порядку, по шагу на вызов, затем повторяется, поэтому один и тот же тест даёт одну и ту же цепочку статусов на каждом прогоне. Долю ошибок берите только тогда, когда случайность нужна намеренно.
Как посмотреть, сколько раз клиент повторил запрос?
Инспектор перечисляет каждую доставку со временем, поэтому число попыток — это число запросов, а back-off — интервалы между ними. Так же ловится клиент, который повторяет заметно чаще, чем задумано.
Можно ли сымитировать зависший запрос вместо ошибки?
Да, задайте задержку ответа. Это случай, который пропускает большинство тестов ретраев: клиент без таймаута навсегда встаёт на первой попытке, и его логика повторов не выполняется вовсе.

Собери свой

Создать мок

Похожие гайды

← Все гайды

Обновлено: 2026-09-08