Asserting array of arrays with JSONPath and spring mvc
Asked Answered
R

5

34

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")));
  }
Ronn answered 2/9, 2014 at 1:18 Comment(0)
B
44

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("/"));
Barone answered 14/4, 2015 at 10:27 Comment(3)
Do you know if there is a way to do this without hardcoding the array indices (in case the order is different)?Sancha
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/JsonPathBarone
This approach won't work for HashSet because the order of elements is not deterministicSchild
C
11

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")))));
Charterhouse answered 13/12, 2020 at 4:28 Comment(0)
H
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 :)

Hohenzollern answered 16/1, 2019 at 5:29 Comment(0)
M
2

you can try :

mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
    .andExpect(jsonPath("$.links[*].rel[*]", containsInAnyOrder("self")))
    .andExpect(jsonPath("$.links[*].href[*]", containsInAnyOrder("/")))
Maureenmaureene answered 5/4, 2022 at 14:12 Comment(0)
R
1

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/

Rogozen answered 15/2 at 14:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.