подсчитать членов с помощью jsonpath?

103

Можно ли подсчитать количество членов с помощью 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. Является ли это возможным? Также приветствуются альтернативные решения.

NA.
источник

Ответы:

233

Чтобы проверить размер массива :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-library и import static org.hamcrest.Matchers.*;для работы hasSize ().

лописан
источник
2
@mattb - при использовании Maven не добавляйте hamcrest-allв качестве зависимости, а используйте hamcrest-library: code.google.com/p/hamcrest/wiki/HamcrestDistributables
Адам Михалик
1
Что делать, если человек не знает размера и хочет его получить?
zygimantus 02
2
@ menuka-ishan - я не думаю, что он устарел, согласно: MockMvcResultMatchers.jsonPath () javadoc
lopisan
@zygimantus, вы должны подсчитать размер всех полей в вашем объекте / массиве либо из исходного кода, либо из средств разработчика веб-браузера, проверяющих ответ.
cellepo
12

Вы также можете использовать методы внутри jsonpath, поэтому вместо

mockMvc.perform(get(API_URL))
   .andExpect(jsonPath("$.*", hasSize(2)));

ты можешь сделать

mockMvc.perform(get(API_URL))
   .andExpect(jsonPath("$.length()", is(2)));
черствый
источник
7

Мы можем использовать функции JsonPath, такие как size()или length(), например:

@Test
public void givenJson_whenGetLengthWithJsonPath_thenGetLength() {
    String jsonString = "{'username':'jhon.user','email':'jhon@company.com','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':'jhon@company.com','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

Сам сегодня разбирался с этим. Не похоже, что это реализовано в доступных утверждениях. Однако есть способ передать 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
    }
})
Бен
источник
0

если у вас нет com.jayway.jsonassert.JsonAssertпути к классам (что было со мной), тестирование следующим образом может быть возможным обходным путем:

assertEquals(expectedLength, ((net.minidev.json.JSONArray)parsedContent.read("$")).size());

[примечание: я предполагал, что содержимое json всегда является массивом]

Танвир
источник