Validating an array within a collection

3,204 views
Skip to first unread message

zerbol...@gmail.com

unread,
Aug 12, 2015, 1:47:39 PM8/12/15
to REST assured
Hello,

I have an array within a collection I'd like to validate. The problem is I can't seem to match the array using hasItems and the array itself. It seems that it is as expected two arrays, but the matcher appears to think they're different I'm not quite sure why. Can anybody help?

Here is the code:



given().get(url).
then().
body(matchesJsonSchemaInClasspath("Schema.json"))
.and()
.body("id", hasItems("id1234","id5678"))
.and()
.body("name", hasItems("Aname", "AnotherName"))
.and()
.body("categories", hasItems("Item->FirstItem, Item->SecondItem,Item->ThirdItem, Item->FourthItem, Item->FifthItem, Item->SixthItem", "Item->FirstItem"))
.log().body();

I get the following error:

JSON path categories doesn't match.
Expected: (a collection containing 
"Item->FirstItem, Item->SecondItem,Item->ThirdItem, Item->FourthItem, Item->FifthItem, Item->SixthItem", "Item->FirstItem")
  Actual:      [[Item->FirstItem, Item->SecondItem,Item->ThirdItem, Item->FourthItem, Item->FifthItem, Item->SixthItem], [Item->FirstItem]]

And here is the json:

[
  {
    "id": "id1234",
    "name": "Aname",
    "things": [
      "Item->FirstItem",
      "Item->SecondItem",
      "Item->ThirdItem",
      "Item->FourthItem",
      "Item->FifthItem",
      "Item->SixthItem"
    ],
    "site": "www.asite.com",
    "rating": "999",
    "date": "13/12/2015",
    "year": 2015,
    "length": 120,
    "description": {
      "short": "blah.",
      "medium": "blah blah blah",
      "long": "blah blah blah blah blah."
    },
    "passed": true,
    "created": {
      "user": "jimmy",
      "time": "2015-06-22T19:33:56.411Z"
    },
    "updated": {
      "user": "jeff",
      "time": "2015-06-22T19:33:56.411Z"
    }
  },
  {
    "id": "id5678",
    "name": "AnotherName",
    "categories": [
      "Item -> FirstItem"
    ],
    "website": "www.anothersite.com",
    "summary": {
      "short": "blah.",
      "medium": "blah blah."
    },
    "created": {
      "user": "steff",
      "time": "2015-06-22T19:33:56.411Z"
    },
    "updated": {
      "user": "james",
      "time": "2012-04-24T18:25:43.511Z"
    }
  }
]

Thanks,
Zerb

Johan Haleby

unread,
Aug 12, 2015, 2:08:05 PM8/12/15
to rest-a...@googlegroups.com
Hi, 

I think I know what's going on. The path "categories" is located in json objects that is located inside a list o what happens when you do body("categories") is that GPath will return a list of the the matching values. The simplify things image that you have this object instead:

[
 {
    "id": "id5678",
    "name": "AnotherName",
    "categories": "my category"
 }
... 
]

What happens when you do body("categories") is that a list containing the value of "categories" is returned, i.e. ["my category"]. Now back to your example:

[
 {
    "id": "id5678",
    "name": "AnotherName",
    "categories":  [
      "Item -> FirstItem"
    ],
 }
... 
]

Just as before body("categories") returns the value of "categories" that now happens to be a list containing ["Item -> FirstItem"], so that's returned by body("categories") is now a list containing a list containing one element "Item -> FirstItem", i.e. [["Item -> FirstItem"]]. This is why you cannot use the hasItems Hamcrest matcher since it expects a list and not a list of lists. What I usually do in these cases is to flatten the lists before I compare it to the Hamcrest matcher. For example:


.body("categories.flatten()", hasItems("Item->FirstItem, Item->SecondItem,Item->ThirdItem, Item->FourthItem, Item->FifthItem, Item->SixthItem", "Item->FirstItem"))

That ought to do it!

Regards,
/Johan

--
You received this message because you are subscribed to the Google Groups "REST assured" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rest-assured...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Johan Haleby

unread,
Aug 12, 2015, 2:09:13 PM8/12/15
to rest-a...@googlegroups.com
Sorry for all the typos, I was a bit too fast.. Hope it makes sense anyways.

zerbol...@gmail.com

unread,
Aug 13, 2015, 9:39:04 AM8/13/15
to REST assured


On Wednesday, August 12, 2015 at 7:08:05 PM UTC+1, Johan Haleby wrote:
Hi, 

I think I know what's going on. The path "categories" is located in json objects that is located inside a list o what happens when you do body("categories") is that GPath will return a list of the the matching values. The simplify things image that you have this object instead:

[
 {
    "id": "id5678",
    "name": "AnotherName",
    "categories": "my category"
 }
... 
]

What happens when you do body("categories") is that a list containing the value of "categories" is returned, i.e. ["my category"]. Now back to your example:

[
 {
    "id": "id5678",
    "name": "AnotherName",
    "categories":  [
      "Item -> FirstItem"
    ],
 }
... 
]

Just as before body("categories") returns the value of "categories" that now happens to be a list containing ["Item -> FirstItem"], so that's returned by body("categories") is now a list containing a list containing one element "Item -> FirstItem", i.e. [["Item -> FirstItem"]]. This is why you cannot use the hasItems Hamcrest matcher since it expects a list and not a list of lists. What I usually do in these cases is to flatten the lists before I compare it to the Hamcrest matcher. For example:


.body("categories.flatten()", hasItems("Item->FirstItem, Item->SecondItem,Item->ThirdItem, Item->FourthItem, Item->FifthItem, Item->SixthItem", "Item->FirstItem"))

That ought to do it!

Regards,
/Johan

Hi Johan,

Thanks for the response. When I use the above code it seems to just flatten the two lists into one , but the matcher still fails as it expects two collections. 

java.lang.AssertionError: 1 expectation failed.
JSON path categories.flatten() doesn't match.
Expected: (a collection containing "Item->item1, Item->item2, Item->item3, Item->item4, Item->item5, Item->item6" and a collection containing "Item -> item1")
  Actual: ["Item->item1, "Item->item2, "Item->item3, "Item->item4, "Item->item5, "Item->item6, "Item -> item1]

Thanks,
Zerb

zerbol...@gmail.com

unread,
Aug 13, 2015, 9:56:45 AM8/13/15
to REST assured
Sorry that error should be:

java.lang.AssertionError: 1 expectation failed.
JSON path categories.flatten() doesn't match.
Expected: (a collection containing "Item->item1, Item->item2, Item->item3, Item->item4, Item->item5, Item->item6" and a collection containing "Item -> item1")
  Actual: [Item->item1, Item->item2, Item->item3, Item->item4, Item->item5, Item->item6, Item -> item1] 

Cheers,
Zerb

Johan Haleby

unread,
Aug 13, 2015, 10:00:10 AM8/13/15
to rest-a...@googlegroups.com
You're probably doing something like:

.. .body("categories.flatten()", hasItems("Item->item1, Item->item2, Item->item3, Item->item4, Item->item5, Item->item6");

which is not correct. You need to put a " around each element like this:

.. .body("categories.flatten()", hasItems("Item->item1", "Item->item2", "Item->item3", "Item->item4", "Item->item5", "Item->item6");

/Johan


Zerb

--

zerbol...@gmail.com

unread,
Aug 13, 2015, 10:08:37 AM8/13/15
to REST assured


On Thursday, August 13, 2015 at 3:00:10 PM UTC+1, Johan Haleby wrote:
You're probably doing something like:

.. .body("categories.flatten()", hasItems("Item->item1, Item->item2, Item->item3, Item->item4, Item->item5, Item->item6");

which is not correct. You need to put a " around each element like this:

.. .body("categories.flatten()", hasItems("Item->item1", "Item->item2", "Item->item3", "Item->item4", "Item->item5", "Item->item6");

/Johan


HI Johan,

Sorry a bit new to the rest assured and hamcrest. You're right, that's working now thanks.

Zerb 

Johan Haleby

unread,
Aug 13, 2015, 10:17:36 AM8/13/15
to rest-a...@googlegroups.com
No problem, glad you got it working


Zerb 

--
Reply all
Reply to author
Forward
0 new messages