在Spring MVC测试中使用过滤器的JsonPath表达式

时间:2016-11-17 11:49:55

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

我有一个控制器,它返回一个部分列表。每个部分都有一个类型。我想测试类型" JOB"的部分。有一个领域"功能"大小为3。

这是我的代码:

mockMvc.perform(get(url)
        .contentType(MediaTypes.HAL_JSON)
        .accept(MediaTypes.HAL_JSON))
        .andDo(print())
        .andExpect(status().isOk())
        .andExpect(jsonPath("$._embedded.content", 
                hasSize(equalTo(2))))
        .andExpect(jsonPath("$._embedded.content[?(@.type=='JOB')].functions", 
                hasSize(equalTo(3))));

控制器返回的JSON(简化为易读性):

{
   "_embedded":{
      "content":[
         {
            "subsections":null,
            "type":"PROFILE",
            "createdDate":null,
            "lastModifiedDate":null
         },
         {
            "functions":[
               {
                  "rank":845131,
                  "function":"9IXZT"
               },
               {
                  "rank":82701,
                  "function":"T91WX"
               },
               {
                  "rank":98686,
                  "function":"PA7NA"
               }
            ],
            "type":"JOB",
            "createdDate":null,
            "lastModifiedDate":null
         }
      ]
   }
}

我使用this tool对该JSON测试了表达式并且正常工作,但在运行测试时我得到了这个断言错误:

java.lang.AssertionError: JSON path "$._embedded.content[?(@.type=='JOB')].functions"
Expected: a collection with size <3>
    but: collection size was <1>
        at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
        at org.springframework.test.util.JsonPathExpectationsHelper.assertValue(JsonPathExpectationsHelper.java:74)
        at org.springframework.test.web.servlet.result.JsonPathResultMatchers$1.match(JsonPathResultMatchers.java:86)
        at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171)
        ...

2 个答案:

答案 0 :(得分:1)

添加.*时有所不同。当我在JSONPath Expression Tester填写您的数据时 我得到了一个轻微但重要的区别:

<案例1

$._embedded.content[?(@.type=='JOB')].functions收益

[
   [
      {
         "rank":845131,
         "function":"9IXZT"
      },
      {
         "rank":82701,
         "function":"T91WX"
      },
      {
         "rank":98686,
         "function":"PA7NA"
      }
   ]
]
<案例2

$._embedded.content[?(@.type=='JOB')].functions.*产生

[
   {
      "rank":845131,
      "function":"9IXZT"
   },
   {
      "rank":82701,
      "function":"T91WX"
   },
   {
      "rank":98686,
      "function":"PA7NA"
   }
]

因此,对于案例1,当您获取根节点(这是一个数组)时,您将一个元素作为直接子节点:包含三个对象的数组。因此断言找到了一个大小为1的数组(集合)。 对于案例2,您有阵列根节点包含三个对象,导致集合的计数为三。

对于其他实现,可能不是这样。在此示例中,我使用 Flow Communications 下的 JSONPath 0.3.4 实现。

.之后functions将结果的根级别设置为此元素,而*表示将此根目录下的所有元素

我没有足够的信心来解释$._embedded.content[?(@.type=='JOB')].functions背后的确切行为。但我认为它与过滤器?(@.type=='JOB')

有关

https://github.com/json-path/JsonPath#what-is-returned-when

答案 1 :(得分:0)

在表达式的末尾添加。*解决了问题,所以现在它看起来像这样:

$._embedded.content[?(@.type=='JOB')].functions.*

我不明白为什么示例中的第一个表达式有效但我必须将。*添加到第二个表达式。如果有人知道,请解释。