Подтвердить что ты не робот

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

4b9b3361

Ответ 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)));