Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hamcrest test that a map contains all entries from another map

Tags:

java

hamcrest

I want to check that a map contains a certain set of entries. It is allowed to contain other entries that are not in expectedMap. I currently have the following assertion:

assertThat(expectedMap.entrySet(), everyItem(isIn(actualMap.entrySet())));

Although this does work, the failure message that it prints is confusing because the expected and received arguments have been reversed from normal usage. Is there a better way to write it?

like image 550
z7sg Ѫ Avatar asked Jan 17 '14 12:01

z7sg Ѫ


1 Answers

hasItems does what you want, but in a non-obvious way. You have to jump through some hoops as Hamcrest has relatively limited support for matching Iterables. (Without going into detail, this is due to the vagaries of how Java generics work- I'll post some more links with detail later).

(I'm assuming you're using generics, e.g. Map<String, String> as opposed to simply Map).

In the meantime you have a couple of options...

If you are happy with test code that raises warnings / using @SuppressWarnings("unchecked") in your test:

assertThat(actualMap.entrySet(), (Matcher)hasItems(expectedMap.entrySet().toArray()));

Explanation: there is no overload of hasItems that takes a Set or Iterable, but it will take an array. Set.toArray() returns Object[], which won't match assertThat against your actualMap.entrySet() - but if you erase the declared type of the Matcher, it will happily proceed.

If you want an assertion that compiles without warnings, it gets uglier - you need to copy the Set into some kind of Iterable<Object> (you can't cast) in order to match on the Objects :

assertThat(new HashSet<Object>(actualMap.entrySet()), hasItems(expectedMap.entrySet().toArray()));

But to be perfectly honest, for clarity you are almost certainly best off asserting each entry individually:

for (Entry<String, String> entry : expectedMap.entrySet()) {
    assertThat(actualMap, hasEntry(entry.getKey(), entry.getValue())); 
}

...or you could write your own Matcher - there are plenty of resources on how to do this online and on SO.

like image 193
bacar Avatar answered Sep 22 '22 20:09

bacar