it-swarm.com.ru

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

Можно ли посчитать количество членов, использующих JsonPath?

Используя spring mvc test я тестирую контроллер, который генерирует 

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

77
NA.

Чтобы проверить размер array: jsonPath("$", hasSize(4)) 

Для подсчета членов object: jsonPath("$.*", hasSize(4)) 


То есть чтобы проверить, что API возвращает array из 4 элементов:

допустимое значение: [1,2,3,4]

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

чтобы проверить, что API возвращает object, содержащий 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 ().

169
lopisan

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

Мы можем использовать функции 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 и получим размер de:

  @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 |

Пример кода можно найти здесь .

2
SHoko

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

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

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

0
Tanvir

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

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

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

mockMvc.perform(get(API_URL))
   .andExpect(jsonPath("$.length()", is(2)));
0
stalet