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