Считать членов с jsonpath?
Можно ли подсчитать количество членов с помощью JsonPath?
Использование spring тест mvc Я тестирую контроллер, который генерирует
{"foo": "oof", "bar": "rab"}
с
standaloneSetup(new FooController(fooService)).build()
.perform(get("/something").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(jsonPath("$.foo").value("oof"))
.andExpect(jsonPath("$.bar").value("rab"));
Я хотел бы убедиться, что в сгенерированном json нет других членов. Надеюсь, посчитав их с помощью jsonPath. Является ли это возможным? Альтернативные решения также приветствуются.
Ответы
Ответ 1
Чтобы проверить размер массива: jsonPath("$", hasSize(4))
Для подсчета членов объекта: jsonPath("$.*", hasSize(4))
Т.е. чтобы проверить, что API возвращает массив из 4 элементов:
допустимое значение: [1,2,3,4]
mockMvc.perform(get(API_URL))
.andExpect(jsonPath("$", hasSize(4)));
чтобы проверить, что API возвращает объект, содержащий 2 члена:
допустимое значение: {"foo": "oof", "bar": "rab"}
mockMvc.perform(get(API_URL))
.andExpect(jsonPath("$.*", hasSize(2)));
Я использую Hamcrest версии 1.3 и Spring Test 3.2.5.RELEASE
hasSize (int) Javadoc
Примечание: вам нужно включить зависимость от библиотеки hamcrest и import static org.hamcrest.Matchers.*;
чтобы hasSize() работал.
Ответ 2
Сегодня я занимаюсь этим. Кажется, что это не реализовано в доступных утверждениях. Однако есть способ передать объект org.hamcrest.Matcher
. С этим вы можете сделать что-то вроде следующего:
final int count = 4; // expected count
jsonPath("$").value(new BaseMatcher() {
@Override
public boolean matches(Object obj) {
return obj instanceof JSONObject && ((JSONObject) obj).size() == count;
}
@Override
public void describeTo(Description description) {
// nothing for now
}
})
Ответ 3
Мы можем использовать функции JsonPath, такие как size()
или length()
, например:
@Test
public void givenJson_whenGetLengthWithJsonPath_thenGetLength() {
String jsonString = "{'username':'jhon.user','email':'[email protected]','age':'28'}";
int length = JsonPath
.parse(jsonString)
.read("$.length()");
assertThat(length).isEqualTo(3);
}
Или просто net.minidev.json.JSONObject
и получите размер:
@Test
public void givenJson_whenParseObject_thenGetSize() {
String jsonString = "{'username':'jhon.user','email':'[email protected]','age':'28'}";
JSONObject jsonObject = (JSONObject) JSONValue.parse(jsonString);
assertThat(jsonObject)
.size()
.isEqualTo(3);
}
Действительно, второй подход выглядит лучше, чем первый. Я сделал тест производительности JMH, и я получил следующие результаты:
| Benchmark | Mode | Cnt | Score | Error | Units |
|-------------------------------------------------|-------|-----|-------------|--------------|-------|
| JsonPathBenchmark.benchmarkJSONObjectParse | thrpt | 5 | 3241471.044 | ±1718855.506 | ops/s |
| JsonPathBenchmark.benchmarkJsonPathObjectLength | thrpt | 5 | 1680492.243 | ±132492.697 | ops/s |
Пример кода можно найти здесь.
Ответ 4
если у вас нет com.jayway.jsonassert.JsonAssert
в вашем пути к классам (что было со мной), тестирование следующим способом может быть возможным обходным путем:
assertEquals(expectedLength, ((net.minidev.json.JSONArray)parsedContent.read("$")).size());
[примечание: я предположил, что содержимое json всегда является массивом]
Ответ 5
Вы также можете использовать методы внутри jsonpath, поэтому вместо
mockMvc.perform(get(API_URL))
.andExpect(jsonPath("$.*", hasSize(2)));
ты можешь сделать
mockMvc.perform(get(API_URL))
.andExpect(jsonPath("$.length()", is(2)));