Spring MVC Test with Hamcrest and JsonPath: How count the body size? (not count members)
Asked Answered
Q

1

5

I am working with:

  • Spring MVC Test
  • Hamcrest
  • JsonPath

I have the following how a response from the server:

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = {Content-Type=[application/json;charset=UTF-8]}
     Content type = application/json;charset=UTF-8
             Body = {
  "id" : "100",
  "nombre" : "Jesús Você",
  "apellido" : "Mão Nuñez",
  "fecha" : "1977-12-08"
}
    Forwarded URL = null
   Redirected URL = null

The following works as expected (is valid):

 .andExpect(jsonPath("$").exists())
 .andExpect(jsonPath("$", notNullValue()))
 .andExpect(jsonPath("$", isA(LinkedHashMap.class)))

 .andExpect(jsonPath("$.*").exists())
 .andExpect(jsonPath("$.*", notNullValue()))
 .andExpect(jsonPath("$.*", isA(JSONArray.class)))
 .andExpect(jsonPath("$.*", hasSize(is(4))))

I need test that ("$") is 1. Confirm exists 1 item. It to confirm again the following:

Body = {
      "id" : "100",
      "nombre" : "Jesús Você",
      "apellido" : "Mão Nuñez",
      "fecha" : "1977-12-08"
    }

I've tried:

.andExpect(jsonPath("$", hasSize(is(1))))

Observe the difference between $ and $.*, for the latter I know it counts the number of fields. But from the former I always get:

java.lang.AssertionError: JSON path "$"
Expected: a collection with size is <1>
     but: was <{id=100, nombre=Jesús Você, apellido=Mão Nuñez, fecha=1977-12-08}>
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:18

'Seems' the data is not a collection, but remember that .andExpect(jsonPath("$", isA(LinkedHashMap.class))) pass. I am confused in someway.

Therefore is possible test that ("$") is 1.? If yes, how?.

I've read count members with jsonpath?

And says:

To test size of array: jsonPath("$", hasSize(4))

To count members of object: jsonPath("$.*", hasSize(4))

My data returned is not an array, it is a LinkedHashMap.class because if I use .andExpect(jsonPath("$").isArray()) I get:

java.lang.AssertionError: Expected an array at JSON path "$" but found: {id=100, nombre=Jesús Você, apellido=Mão Nuñez, fecha=1977-12-08}
Expected: an instance of java.util.List
     but: <{id=100, nombre=Jesús Você, apellido=Mão Nuñez, fecha=1977-12-08}> is a java.util.LinkedHashMap

BTW: .andExpect(jsonPath("$.*").isArray()) pass.

Quadrivalent answered 13/9, 2016 at 15:20 Comment(8)
I need test that ("$") is 1. Confirm exists 1 item. I've re-read this a few times but stil can't understand it. What does 1 exactly mean here?Posterior
The following Body = { "id" : "100", "nombre" : "Jesús Você", "apellido" : "Mão Nuñez", "fecha" : "1977-12-08" } is just one item with four fields. Therefore $.* represents the item with four fields. But I need to test the item (I thought $ should be enough but fails).Quadrivalent
Hm, but what's wrong with jsonPath("$").exists() then?Posterior
Is valid, just curios if is possible in the other way. What happens if the result returns two items. jsonPath("$").exists() should pass too but It does not care if was 1 or 2 items.Quadrivalent
But how do you get more than two JSON items as the root at once? It should fail due to a syntax error or whatever else reason, but this must be illegal anyway.Posterior
Yes, should fail because is not an array (I have just one item). Remember To test size of array: jsonPath("$", hasSize(4)) pass when is an array with many items, in this case 4.Quadrivalent
It must be specifics of the hasSize() matcher which seems to accept both root arrays or root array elements expression. You can write your matcher to substitute hasSize(). Sorry, I'm still blind to see the rationale behind your request. :)Posterior
That's the point accept both root arrays or root array for the latter or root array the hasSize() does not work.Quadrivalent
R
7

To validate the size of a Map instead of:

.andExpect(jsonPath("$", hasSize(1)))

you should use:

.andExpect(jsonPath("$", aMapWithSize(1)))

Note: Check this link with org.hamcrest.Matchers javadoc

Resistencia answered 16/12, 2021 at 11:51 Comment(4)
Where is declared aMapWithSize? Your link does not include itQuadrivalent
@Manuel Jordan, I looked and found this: hamcrest.org/JavaHamcrest/javadoc/2.0.0.0/org/hamcrest/…Pretension
@alfonsosolis consider to update the "Note" part is not clear - thanks for the link @D.Kastier!Quadrivalent
I updated the link ... ManuelJordan and @Pretension thanks for pointing it outResistencia

© 2022 - 2024 — McMap. All rights reserved.