'Asserting array of arrays with JSONPath and spring mvc

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


Solution 1:[1]

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("/"));

Solution 2:[2]

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

Solution 3:[3]

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;

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

Solution 4:[4]

you can try :

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Akmal Rakhimov
Solution 2 moffeltje
Solution 3 Menuka Ishan
Solution 4 Ahmed Ashref