120

是否可以使用 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 计算它们。是否可以?也欢迎替代解决方案。

4

5 回答 5

283

要测试数组的大小:jsonPath("$", hasSize(4))

要计算object的成员: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() 才能工作。

于 2013-12-10T15:52:04.063 回答
21

您还可以使用 jsonpath 中的方法,所以而不是

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

你可以做

mockMvc.perform(get(API_URL))
   .andExpect(jsonPath("$.length()", is(2)));
于 2018-11-22T14:42:04.223 回答
10

我们可以使用类似or的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 |

示例代码可以在这里找到。

于 2018-08-06T17:08:18.210 回答
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
    }
})
于 2012-12-28T23:33:42.470 回答
0

如果您com.jayway.jsonassert.JsonAssert的类路径中没有(我就是这种情况),则以以下方式进行测试可能是一种可能的解决方法:

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

[注意:我假设 json 的内容总是一个数组]

于 2015-11-27T20:55:35.493 回答