用jsonpath计算成员?

时间:2012-12-06 14:08:42

标签: java spring testing jsonpath spring-test-mvc

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

5 个答案:

答案 0 :(得分:183)

测试数组的大小: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()正常工作。

答案 1 :(得分: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
    }
})

答案 2 :(得分:3)

我们可以像这样size()length()这样使用JsonPath functions

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

可以找到示例代码here

答案 3 :(得分:0)

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

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

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

答案 4 :(得分:0)

您还可以使用jsonpath内部的方法,所以代替

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

你可以做

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