Сервис отвечает HTTP 204 No Content, но отправляет тело ответа. Какой дефект HTTP-контракта должен выявить интеграционный тест?
Интеграционный тест должен выявить, что ответ 204 No Content содержит недопустимое тело. Для этого нужно проверять не только статус, но и отсутствие байтов содержимого после заголовков.
Если клиенту действительно нужно вернуть данные, сервер должен использовать статус, допускающий представление, например 200 OK, а не 204.
HTTP разделяет успешность операции и наличие представления ресурса. Статус 204 предназначен для успешного результата без содержимого, поэтому клиент может завершить обработку сразу после получения заголовков.
Такое различие уменьшает неоднозначность между сервером, клиентом и промежуточными узлами: клиенту не нужно угадывать, следует ли ему читать тело, разбирать JSON или ожидать дополнительные данные.
Нарушение может появиться из-за общего обработчика ответов, middleware с диагностическим сообщением или ошибочной сериализации значения после выбора статуса 204. Проверка только кода ответа пропустит такой дефект.
Последствия зависят от клиента и версии HTTP. Клиент может проигнорировать тело, завершить разбор с ошибкой или некорректно обработать последующие данные; промежуточный узел также может интерпретировать лишние байты иначе. В результате один и тот же API будет вести себя нестабильно для разных потребителей.
Интеграционная проверка должна подтвердить три свойства:
Проверять нужно фактически полученные байты, а не только результат вызова метода вроде «получить JSON». Если клиентская библиотека автоматически скрывает нарушение, полезно дополнительно проверять ответ на уровне HTTP-клиента или использовать инструмент, позволяющий увидеть необработанное тело.
Заголовки, описывающие метаданные операции, сами по себе не являются телом. Например, при успешном удалении сервер может вернуть 204 и заголовки, но не JSON-сообщение с результатом. Если нужно передать идентификатор, итоговое состояние или предупреждение, контракт должен выбрать статус, допускающий содержимое, чаще всего 200.
После успешного удаления ресурса API стало возвращать 204, но общий middleware добавлял JSON с текстом операции. Часть клиентов игнорировала тело, а другой клиент завершал обработку ошибкой из-за неожиданного содержимого.
Рассматривались два варианта. Можно было оставить 204 и специально удалять тело: это сохраняло семантику ответа без представления, но требовало гарантировать, что другие middleware не добавят содержимое. Второй вариант — заменить статус на 200 и формально описать JSON-ответ; он был проще для текущих клиентов, но менял контракт и требовал обновления документации.
Выбрали первый вариант, поскольку операция не должна была возвращать данные. Интеграционный тест проверил статус, отсутствие тела и отсутствие сериализации в успешной ветке. Это предотвратило повторное появление дефекта при изменении общего обработчика ответов.
Нет. Сам по себе заголовок не заменяет проверку фактически полученного содержимого и может отсутствовать или обрабатываться клиентской библиотекой. Надёжнее проверить, что после получения ответа потребителю действительно передано ноль байтов тела.
Нет. Контракт определяется семантикой HTTP-ответа, а не удачным поведением одного клиента. Игнорирование лишнего содержимого маскирует нарушение и не гарантирует совместимость с другими клиентами, прокси и реализациями HTTP.
Нет. Интеграционные тесты должны проверять это свойство для всех операций, объявленных контрактом как возвращающие 204, включая разные ветки успеха. Особенно важны общие обработчики, middleware и ответы после удаления или изменения ресурса: именно они часто добавляют тело непреднамеренно.