0

I have a controller that returns a list of sections. Each of these sections have a type. I want to test that the section of type "JOB" have a field "functions" with a size of 3.

Here is my code:

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))));

The JSON returned by the controller (simplified for legibility):

{
   "_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
         }
      ]
   }
}

I tested the expression with this tool against that JSON and works correctly, but when running the test I'm getting this assertion error:

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 Answers 2

3

There is a difference when adding the .*. When I fill in your data at JSONPath Expression Tester I get a slight but important difference:

Case 1

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

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

Case 2

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

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

So for case 1 when you take the root node (which is an array) you have one element as direct child: the array containing three objects. Therefore the assertion found an array (collection) whith size one. For case 2 you have the array root node containing three objects leading to a count of three for the collection.

Maybe this is not true for other implementations. In this example I used the JSONPath 0.3.4 Implementation under Flow Communications.


The . after functions sets the root level of the result to this element and * means take all elements under this root.

I am not confident enough to explain the exact behaviour behind $._embedded.content[?(@.type=='JOB')].functions. But I think it has something to do with the filter ?(@.type=='JOB')

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

Sign up to request clarification or add additional context in comments.

1 Comment

Great explanation! Thank you!
1

Adding .* to the end of the expression solved the problem, so now it looks like this:

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

I don't understand why the first expression in the example is working but I have to add .* to the second one. If someone knows, please explain.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.