37

I'm having difficulty figuring out how to assert with jsonPath in a JSON document response in spring mvc. Perhaps there's a better way of accomplishing this than using jsonPath for this particular scenario. I would like to validate that the links array has a rel item of "self" and that "href" attribute of the object of "self" also has an "href" attribute which is equal to "/". The JSON response looks like this:

 {  
   "links":[  
      {  
         "rel":[  
            "self"
         ],
         "href":"/"
      },
      {  
         "rel":[  
            "next"
         ],
         "href":"/1"
      }
   ]
}

I tried this where I can see that it has rel [0] has self but I would prefer to not rely on where in the links array and rel array the self is and actually test what that href is at links[rel][self] is "/". Any ideas?

 @Before
  public void setup() {
    MockitoAnnotations.initMocks(this);
    mockMvc = MockMvcBuilders.standaloneSetup(welcomeController).build();
  }

  @Test
  public void givenRootUrl_thenReturnLinkToSelf() throws Exception {
    mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
        .andExpect(jsonPath("$.links[0].rel[0].", is("self")));
  }

5 Answers 5

46

How about adding several andExpect methods? Something similar to:

mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
    .andExpect(jsonPath("$.links[0].rel[0]", is("self")))
    .andExpect(jsonPath("$.links[0].href[0]", is("/"));
Sign up to request clarification or add additional context in comments.

3 Comments

Do you know if there is a way to do this without hardcoding the array indices (in case the order is different)?
Kevin, you can use regexp in your jsonpath, like this $.links[?(@.rel =~ /.*self/i)] or something like this. Please, check full documentation here: github.com/json-path/JsonPath
This approach won't work for HashSet because the order of elements is not deterministic
12

I guess you could do it like this if you don't want to hardcode array index value

MockMvc.perform(get("/"))
.andDo(print()).andExpect(status().isOk())
.andExpect(jsonPath("$.links[*].rel").value(Matchers.containsInAnyOrder(Matchers.containsInAnyOrder(Matchers.is("self")))));

Comments

8

The Accepted answer looks alright to me. But I am not familiar with junit4. Therefore I will add here how I would test a typical scenario using Junit5.

mockMvc.perform(get("/"))
    .andDo(print())
    .andExpect(status().isOk())
    .andExpect(jsonPath("$.links", hasSize(2)))
    .andExpect(jsonPath("$.links[0].rel[0]")
        .value("self"))
    .andExpect(jsonPath("$.links[0].href[0]")
        .value("/"))

I will here add static imports(in case of a beginner) because when first I was working of I had to figure which imports within several imports.

import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.Matchers.hasSize;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.hamcrest.CoreMatchers.is;

Hope this is helpful for someone. especially someone new to unit testing :)

Comments

3

you can try :

mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
    .andExpect(jsonPath("$.links[*].rel[*]", containsInAnyOrder("self")))
    .andExpect(jsonPath("$.links[*].href[*]", containsInAnyOrder("/")))

Comments

2

I know a very old post and you have probably figured it out already, but for the sake of new devs wondering this question, like me.

You can use the following.

import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasSize;
.......AdditionalCode
.andExpect(jsonPath("$.path").isArray())
.andExpect(jsonPath("$.path").value(hasSize(2))
.andExpect(jsonPath("$.path").value(hasItem("self!"))

Source => https://mkyong.com/spring-boot/spring-test-how-to-test-a-json-array-in-jsonpath/

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.