Что происходит при неполной передаче данных в PUT запросе
Что проверяют
Понимаете ли вы семантику PUT по спецификации и умеете ли отделять два совсем разных дефекта, которые прячутся за одной формулировкой: клиент прислал не все поля, и тело запроса физически оборвалось.
Как отвечать
По спецификации PUT замещает ресурс целиком присланным представлением. То есть неполное тело это не частичное обновление, а новое состояние, в котором части полей нет, и сервер по контракту должен либо отвергнуть такой запрос, либо привести отсутствующие поля к значению по умолчанию. Частичное обновление это PATCH.
Дальше развилка, и её стоит проговорить явно:
- данных не хватает на уровне содержимого: обязательное поле отсутствует, сервер отвечает
400или422с описанием, ресурс не меняется. Если поле необязательное, важно зафиксировать, что именно делает сервер, сбрасывает значение или сохраняет прежнее; - тело оборвалось на уровне транспорта: длина не совпала с заголовком
Content-Length, в chunked-передаче не пришёл завершающий кусок. Это уже не валидация, запрос целиком не получен, и ресурс меняться не должен вовсе.
Что проверять: код ответа, тело ошибки в принятом для API формате и обязательно состояние ресурса запросом GET следом. Плюс идемпотентность: два одинаковых PUT подряд дают одно и то же состояние, и на этом свойстве строится проверка повторной отправки после обрыва связи.
Где спотыкаются
Смотрят только на код ответа. Тест видит 400 и зеленеет, а ресурс к этому моменту уже обновлён наполовину, потому что валидация в сервисе идёт вперемешку с записью. Контрольный GET после каждого негативного сценария снимает целый класс таких находок.
Второе: считают отсутствующее поле и явный null одним случаем. Это разные входные данные и обычно разное поведение: отсутствие означает, что в новом представлении поля нет, а null означает явное обнуление. Один тест на оба варианта пропускает половину дефектов.
Третье: ждут от PUT поведения PATCH или наоборот. Прежде чем заводить дефект, надо смотреть в контракт: если команда договорилась, что непереданные поля затираются, то сохранение старых значений и есть баг, каким бы удобным оно ни выглядело.