JUnit + Hamcrest: Verifying unordered collections

Mike Kowdley
1 min readJan 14, 2021

There’s many ways to skin a cat, but it took me a while to find a pattern that I liked to verify the contents of a list.

In this case I am looking at an unordered list — it could be something backed by a HashSet<>, or it could be something that came out of ElasticSearch and the order isn’t deterministic.

My goals:

  • Verify some of the properties, only the ones necessary for my test
  • Minimize Boilerplate
  • Ignore the order of items in the collection

Here’s where I ended up:

import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
...assertThat(list, containsInAnyOrder(
allOf(
hasProperty("id", equalTo(1L)),
hasProperty("status", equalTo(Status.UNPUBLISHED))
),
allOf(
hasProperty("id", equalTo(2L)),
hasProperty("status", equalTo(Status.UNPUBLISHED))
)
));

Hope this helps! Would love to see others’ examples that solve this same problem with the best possible failure messages, for both error cases:

  • List has an extra item
  • List is missing an item

When the has an extra item, I get the somewhat helpful:

Expected: iterable over [(hasProperty("id", <1L>) and hasProperty("status", <UNPUBLISHED>)), (hasProperty("campaignId", <2L>) and hasProperty("status", <UNPUBLISHED>))] in any order
but: Not matched: <com.mike.Item@5352c3ac>

When the list is missing an item, I a better one:

No item matches: (hasProperty("id", <6L>) and hasProperty("status", <UNPUBLISHED>))

I’ll continue to look for ways to improve the first one.

--

--