Как тестировать REST API содержимое JSON ответа с вложенными объектами
Что проверяют
Умеете ли вы проверять структуру ответа точечно и устойчиво, а не сравнением строк или одной проверкой статуса. Следом обычно спрашивают, как проверить массив внутри вложенного объекта без привязки к порядку и как отличить отсутствующее поле от поля со значением null.
Как отвечать
Назовите инструменты и когда какой уместен:
- REST Assured и Hamcrest: пути в синтаксисе GPath.
body("order.customer.name", equalTo("Анна")), размер массиваbody("order.items.size()", is(3)), поиск элементаbody("order.items.find { it.sku == 'A1' }.qty", equalTo(2)), проверка всех элементовbody("order.items.price", everyItem(greaterThan(0))); - десериализация в DTO:
.extract().as(OrderDto.class)и сравнение через AssertJusingRecursiveComparison().ignoringFields("id", "createdAt"). Удобно, когда объект большой и проверять нужно почти всё; - JSON Schema: модуль
json-schema-validatorиmatchesJsonSchemaInClasspath("order.json"). Проверяет типы, обязательные поля и вложенность, ловит сломанный контракт; - JSONAssert: сравнение с эталоном в режиме
LENIENT, где лишние поля и порядок в массивах не мешают, или вSTRICT; - тесты контроллера в Spring:
MockMvcсjsonPath("$.order.items[0].sku"). Здесь синтаксис Jayway JsonPath, а не GPath, путать их не стоит.
Отдельно скажите про окружение: тест не ходит на живой внешний адрес. Внешние зависимости подменяют через WireMock, базу поднимают в Testcontainers. Тесты пишут на JUnit Jupiter, а не на org.junit.Test из JUnit 4.
Где спотыкаются
Сравнивают ответ целиком как строку. Тест ломается от порядка полей, пробелов, сгенерированных id и дат.
Завязываются на индекс items[0], когда порядок в ответе не гарантирован. Надёжнее искать элемент по признаку или проверять набор через hasItems.
Не различают отсутствующее поле и null. В REST Assured nullValue() пройдёт в обоих случаях, поэтому наличие ключа проверяют отдельно через hasKey.