У меня есть конечная точка API, которая при вызове с помощью GET возвращает массив объектов JSON в теле, например:
[
{"id": "321", "created": "2019-03-01", "updated": "2019-03-15"},
{"id": "123", "created": "2019-03-02", "updated": "2019-03-16"}
]
Я хотел бы проверить тело с помощью теста Spring MockMvc,Оператор в настоящее время выглядит следующим образом:
mockMvc.perform(get("/myapi/v1/goodstuff").
andExpect(status().isOk()).
andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)).
andExpect(jsonPath("$.*", isA(ArrayList.class))).
andExpect(jsonPath("$.*", hasSize(2))).
andExpect(jsonPath("$[0].id", is("321"))).
andExpect(jsonPath("$[0].created", is("2019-03-01"))).
andExpect(jsonPath("$[0].updated*", is("2019-03-15"))).
andExpect(jsonPath("$[1].id", is("1232"))).
andExpect(jsonPath("$[1].created", is("2019-03-02"))).
andExpect(jsonPath("$[1].updated*", is("2019-03-16")));
Однако реализация моего API не гарантирует порядок объекта JSON в возвращаемом массиве.Если бы это был массив строк, я бы решил это с помощью matcher, сгенерированного org.hamcrest.collection.IsIterableContainingInAnyOrder<T>.containsInAnyOrder
.Но я не вижу ни подходящего сопоставителя для моей ситуации в их документе , ни какой-либо подсказки в описании jsonPath
метода в Spring docs
Из быстрого поискаМне так и не удалось найти ничего, связанного с моей ситуацией на SO, кроме списка строк ситуации , который я описал выше.Конечно, я мог бы преобразовывать объекты JSON в строки.
Но мне интересно, мог бы я решить эту проблему для списка объектов JSON, сравнивая каждое из полей каждого объекта по одному (например,показано в приведенном выше фрагменте кода), но игнорируете порядок объектов в коллекции?
Обновление : Згурский предложил решение, котороепомогает с моим оригинальным упрощенным примером.Тем не менее, на реальном практическом примере есть еще 2 входа:
- количество полей 10-20 вместо 3
- , не все совпадения являются простыми
is
Например:
(немного ближе к моему исходному коду)
mockMvc.perform(get("/myapi/v1/greatstuff").
andExpect(status().isOk()).
andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)).
andExpect(jsonPath("$.*", isA(ArrayList.class))).
andExpect(jsonPath("$.*", hasSize(2))).
andExpect(jsonPath("$[0].id", is("321"))).
andExpect(jsonPath("$[0].did", anything())).
andExpect(jsonPath("$[0].createdTs", startsWith("2019-03-01"))).
andExpect(jsonPath("$[0].updatedTs", startsWith("2019-03-15"))).
andExpect(jsonPath("$[0].name", equalToIgnoringCase("wat"))).
andExpect(jsonPath("$[0].stringValues", containsInAnyOrder("a","b","c"))).
andExpect(jsonPath("$[1].id", is("1232"))).
andExpect(jsonPath("$[1].did", anything())).
andExpect(jsonPath("$[1].createdTs", startsWith("2019-03-01"))).
andExpect(jsonPath("$[1].updatedTs", startsWith("2019-03-15"))).
andExpect(jsonPath("$[1].name", equalToIgnoringCase("taw"))).
andExpect(jsonPath("$[1].stringValues", containsInAnyOrder("d","e","f"))).
andReturn();
Пока что кажется, что я не могу сделать ничего лучше, чем реализовать свой собственный класс matcher.
Или ... можно?