5

I'm using JsonPath to test REST endpoints of my API. My test case looks something like this.

First I create the new object

class Item {         
    String name;
    int id;
    List<String> places;
}
String name = "Randomname" + new Random().nextLong();
JSONObject obj = new Item(name, 3, Arrays.asList("Rome3", "London3", "Paris3"));
post("/items").content(obj);

Then I get a list of all items and check that the item I just created is in the list.

    mockMvc.perform(get("/api/v1/test"))
            .andExpect(jsonPath("$.data[*].name", hasItems("item 1", "item 2")))      // Fine
            .andExpect(jsonPath("$.data[?(@.id == 1)].name", contains("item 1")))
            .andExpect(jsonPath("$.data[?(@.id == 1)].places", contains(contains("Rome1", "London1", "Paris1"))))
            .andReturn();

Which works, but I dont think I'm doing it right because I have a nested contains(contains()). (I've put the full JSON response at the end of this post.)

The problem is that because the JsonPath expressions are returning a list, I need to use a list matcher. For example, instead of writing this

jsonPath("$.data[?(@.id == 1)].name", is("item 1"))

I need to write it like this

jsonPath("$.data[?(@.id == 1)].name", contains("item 1"))

Because the JsonPath expression will return a JSON list of one element

[
    "item 1"
]

Which isn't so bad, but it gets worse with lists, e.g. trying to check if the List of Strings in my variable places contains what I want. The JSON returned is a List of Lists, so this JsonPath expression

jsonPath("$.data[?(@.id == 1)].places"

Will return this

        [ 
            [
                "Rome2",
                "London3",
                "Paris3"
            ]
         ]

So it requires a nested hasItems

jsonPath("$.data[?(@.id == 1)].places", hasItems(hasItems("Rome1", "London1")))

And at that works, but doing this just gives me that feeling that I'm not doing this correctly and I'm missing something.

So my question is, what is the appropriate way to handle checking/matching a list of lists?

Is there a better way to validate the JSON that is being returned by an endpoint?

pdc
  • 134
  • 1
  • 9
  • I feel that the original edit was clearer. – Magnus Dec 23 '15 at 02:25
  • Reverted the changes. – pdc Dec 23 '15 at 03:26
  • 2
    If you can reformulate your jsonpath expression to be definite rather than indefinite, then it should be simpler https://github.com/jayway/JsonPath#what-is-returned-when. However if you cant do that, then im not sure if there are any better options. – Magnus Dec 23 '15 at 04:53

0 Answers0