Как игнорировать порядок элементов в массивах при сравнении JSON в тестах
Что проверяют
Знаете ли вы, что обычное сравнение JSON в Java чувствительно к порядку в массивах, и умеете ли подобрать готовый инструмент вместо самописного компаратора. Следом обычно спрашивают, как игнорировать порядок только в одном поле и что делать с лишними полями в ответе.
Как отвечать
Сначала назовите проблему: List.equals сравнивает элементы по позициям, поэтому ни Map после ObjectMapper.readValue, ни JsonNode.equals порядок в массивах не игнорируют. Порядок ключей объекта им не важен, порядок элементов массива важен.
Дальше готовые средства:
- JSONAssert:
JSONAssert.assertEquals(expected, actual, JSONCompareMode.LENIENT)игнорирует порядок в массивах и разрешает лишние поля. Если лишние поля должны ронять тест, берутNON_EXTENSIBLE: порядок свободный, набор полей строгий. Для точечных правил естьCustomComparator; - Spring MockMvc:
content().json(expected)по умолчанию сравнивает в нестрогом режиме, то есть порядок массивов тоже не учитывается. Строгое сравнение включается отдельно; - JsonUnit:
assertThatJson(actual).when(Option.IGNORING_ARRAY_ORDER).isEqualTo(expected), опции можно применять и к отдельным путям; - AssertJ поверх DTO: десериализовать ответ в объект и сравнить через
usingRecursiveComparison().ignoringCollectionOrder()или проверить список черезcontainsExactlyInAnyOrder.
Сильный ответ заканчивается вопросом к самой задаче: порядок действительно не важен по контракту API? Если сервис обещает сортировку, игнорировать порядок в тесте значит пропустить баг.
Где спотыкаются
Показывают код через Map.equals и уверяют, что он игнорирует порядок. Вложенные List сравниваются по позициям, и тест с переставленными элементами упадёт.
Превращают массив в Set перед сравнением. Дубликаты при этом схлопываются, и [1, 1, 2] становится равным [1, 2].
Включают нестрогий режим сразу для всех тестов. Заодно перестают ловить лишние поля и нарушение сортировки там, где она обещана. Для массивов объектов нестрогое сравнение ещё и дорогое: элементы сопоставляются перебором, на больших ответах это заметно.