Постановка: при сетевом таймауте клиент может повторить запрос создания заказа. Как вручную проверить, что повтор не создаёт дубликат, используя один и тот же ключ операции?
POST /orders HTTP/1.1
Content-Type: application/json
Idempotency-Key: order-2025-001
{"productId":"A-17","quantity":1}
Нужно смоделировать ситуацию, в которой сервер принял запрос, но ответ потерялся: отправить запрос, оборвать ожидание ответа, затем повторить абсолютно такой же запрос с тем же Idempotency-Key. Дефектом будет создание двух заказов или получение при повторе результата, противоречащего первоначальной операции.
Повторная отправка появилась как практическое решение проблемы ненадёжной сети: клиент не всегда может отличить отказ сервера от потери ответа. Для чтения повтор обычно безопасен, но повтор операции создания может привести к двум платежам, заказам или другим побочным эффектам.
Идемпотентность позволяет повторять одну логическую операцию без повторного выполнения её эффекта. Ключ операции связывает несколько сетевых запросов с одной попыткой клиента.
Обычная проверка успешного POST не обнаруживает ошибку: первый запрос создаёт заказ и возвращает ответ. Риск возникает между обработкой запроса сервером и получением ответа клиентом.
Если тестировщик просто отправит два запроса подряд с разными ключами или без контроля состояния, он не докажет, что проверяется именно повтор после таймаута. Неверная проверка может принять два корректно созданных разных заказа за дефект повторной обработки.
Сначала зафиксируйте исходное состояние: в системе нет заказа с идентификатором операции order-2025-001. Затем отправьте запрос и искусственно не дайте клиенту получить ответ: например, временно заблокируйте ответ в прокси после передачи запроса серверу либо отключите соединение в этот момент.
После этого повторите тот же запрос с тем же ключом и тем же телом. Затем проверьте не только ответ, но и фактическое состояние системы: количество заказов, списания, события аудита и связанные побочные эффекты.
Минимальная последовательность выглядит так:
Ключ должен быть одинаковым, иначе сервер вправе рассматривать запросы как разные операции. Тело запроса также должно оставаться тем же: поведение при повторе с изменёнными параметрами является отдельным контрактом.
Важно проверить границы механизма. Если ключ уже использован с другим телом запроса, безопасное поведение обычно требует явного отказа, а не молчаливого выполнения новой операции; точный результат должен следовать спецификации продукта. Также нужно проверить срок хранения ключа: повтор после его истечения может обрабатываться иначе, но это не следует смешивать с базовой проверкой.
В интернет-магазине тестировщик отправил запрос создания заказа через прокси и заблокировал ответ после появления записи в базе. Повтор с тем же ключом вернул успешный ответ, но в интерфейсе обнаружились два заказа с одинаковым составом.
Рассматривались два варианта. Проверка только HTTP-ответов была бы быстрой, но не обнаружила бы дублирование побочного эффекта. Проверка только базы данных дала бы точный результат, но не показала бы, как клиент воспринимает повтор.
Выбрали совместную проверку: сетевой сценарий через прокси, затем сверка ответа, списка заказов и записи аудита. Дефект классифицировали как нарушение идемпотентности операции создания; после исправления повтор возвращал результат одной операции и не создавал вторую запись.
1. Достаточно ли дважды отправить одинаковый запрос с одним ключом?
Нет. Такая проверка может подтвердить только поведение при обычном последовательном повторе. Нужно создать неопределённость результата первого запроса: потерять ответ, задержать его или повторить запрос до получения первого ответа. Иначе не проверяется основной сценарий, ради которого нужна идемпотентность.
2. Что проверять, если повторный запрос получает ошибку?
Нужно сопоставить ошибку с контрактом. Если первая операция уже успешно завершена, повтор не должен приводить к новой операции; он может вернуть сохранённый успешный результат либо специальный ответ о повторе. Если первая операция завершилась бизнес-ошибкой, важно проверить, сохраняется ли её результат и не превращается ли повтор в неожиданное успешное выполнение.
3. Почему нельзя ограничиться проверкой количества заказов?
Один заказ ещё не доказывает отсутствие дублирования побочных эффектов. Система могла создать два платежа, два сообщения или два резервирования, а затем оставить один заказ после очистки. Поэтому проверяют все значимые эффекты операции и их согласованность, а не только одну видимую сущность.