JUnit + Hamcrest: Verifying unordered collections
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.