Клиент отправляет JSON-тело с неподдерживаемым значением Content-Type, но интеграционный тест проверяет только структуру тела. Какой дефект HTTP-контракта останется незамеченным?
Останется незамеченным дефект совместимости по медиа-типу запроса: сервер может не распознать тело как JSON, отклонить запрос или обработать его иначе, хотя сама структура данных корректна. Интеграционный тест должен проверять не только JSON-схему, но и соответствие заголовка Content-Type согласованному контракту.
HTTP передаёт не просто последовательность байтов, а представление ресурса с метаданными о его формате. Заголовок Content-Type появился как способ явно сообщить получателю, как интерпретировать тело сообщения, например как JSON, XML или бинарные данные.
Проверка медиа-типа особенно важна при развитии API: разные форматы могут иметь похожую структуру, но отличаться правилами разбора, версией схемы или семантикой. Поэтому структура тела и тип представления являются разными частями HTTP-контракта.
Тест может распарсить тело как JSON и успешно проверить обязательные поля, даже если реальный HTTP-клиент отправляет неподдерживаемый или ошибочный Content-Type. Такой тест фактически проверяет данные после извлечения из протокола, но не проверяет, сможет ли сервер корректно извлечь эти данные из самого запроса.
В результате в продакшене возможны отказ запроса, неверный выбор обработчика, попытка разобрать тело другим парсером или различия между поведением тестового инструмента и настоящего клиента. Особенно опасно, когда тестовая библиотека автоматически добавляет или исправляет заголовки.
HTTP-контракт должен явно фиксировать допустимый Content-Type для каждого метода и типа тела. Например, если операция принимает JSON, тест должен отправлять запрос с согласованным медиа-типом и проверять успешную обработку, а отдельный негативный сценарий — поведение при неподдерживаемом типе.
Минимальный пример проверки механизма:
В этом примере JSON-схема проверяет поля itemId и quantity, а Content-Type подтверждает, что сервер должен интерпретировать тело именно как JSON. Проверка только схемы не выявит ошибочную отправку, например с типом text/plain или с неподдерживаемым vendor-типом.
Негативная проверка должна быть основана на контракте, а не на случайном поведении конкретного сервера: неподдерживаемый тип должен приводить к согласованному отказу, обычно с HTTP-статусом 415 Unsupported Media Type, если это предусмотрено контрактом. Важно также не смешивать Content-Type, описывающий тело текущего сообщения, и Accept, описывающий предпочтительные типы ответа.
Есть несколько ограничений. Один и тот же формат может иметь параметры, например кодировку или версию медиа-типа, поэтому тесту нужно проверять именно разрешённый набор значений, а не только наличие заголовка. При этом чрезмерно строгая проверка может сделать контракт хрупким, если сервер официально поддерживает несколько совместимых вариантов представления.
Команда проверяла создание заказов. Тест отправлял тело через HTTP-клиент, затем проверял обязательные поля ответа и корректность входной JSON-схемы. После изменения клиентской библиотеки в запросах начал передаваться тип text/json вместо согласованного application/json, но тесты продолжили проходить: вспомогательный слой сам преобразовывал тело в объект до отправки.
Рассматривались три варианта. Проверка только JSON-схемы была простой, но не контролировала HTTP-протокол. Проверка полного запроса в тесте клиента выявляла ошибку, но не подтверждала реальное поведение сервера. Запуск проверки через настоящий HTTP-стек с явным контролем заголовков был дороже, зато проверял границу интеграции целиком.
Выбрали третий вариант и добавили отдельный негативный сценарий для неподдерживаемого медиа-типа. В результате ошибка стала обнаруживаться до выката клиента, а контракт явно зафиксировал допустимый Content-Type и ожидаемую реакцию сервера.
Нет, если контракт различает параметры или версии медиа-типа. Значения application/json и, например, application/vnd.example.order+json могут означать разные правила совместимости, хотя оба связаны с JSON. Проверка должна соответствовать реально поддерживаемому набору типов, включая значимые параметры, но не обязана сравнивать несущественные детали, если сервер официально их игнорирует.
Content-Type отвечает на вопрос, как интерпретировать тело сообщения, а JSON-схема — какие данные допустимы после разбора JSON. Корректное тело может быть отправлено с неподходящим медиа-типом, а запрос с правильным медиа-типом может содержать данные, не соответствующие схеме. Для полноценной проверки нужны оба уровня: протокольный и содержательный.
Только если такое поведение прямо является частью контракта. Иначе чрезмерно снисходительный сервер может скрыть ошибки клиентов и создать неоднозначность при появлении другого обработчика или прокси. Интеграционный тест должен фиксировать требуемое поведение, а не случайную терпимость текущей реализации: принимать разрешённые типы и предсказуемо отклонять неподдерживаемые.