Issue
Let's say I have a Map:
Map<String,Object> map1 = new HashMap<String,Object>();
map1.put("foo1","foo1");
map1.put("foo2", Arrays.asList("foo2","bar2"));
Now I'd like to use Hamcrest matchers to verify the Map's values. If this were a Map< String,String > I would do something similar to this:
assertThat(map1, hasEntry("foo1", "foo1"));
However, I'm stuck when trying to use this with Map where the entries in the Map could be a String or a List of values. This works for the first entry:
assertThat(map1, hasEntry("foo1", (Object)"foo1"));
For the second entry I can't figure out how to setup the Matchers.
EDIT:
I also tried this, but it produces a compiler warning.
assertThat(
map1,
hasEntry(
"foo2",
contains(hasProperty("name", is("foo2")),
hasProperty("name", is("bar2")))));
"The method assertThat(T, Matcher) in the type Assert is not applicable for the arguments (Map, Matcher>>>)"
(The above was the solution here: Hamcrest compare collections )
Solution
You cannot do this elegantly with Hamcrest hasEntry
since it will do type checking when you try to use matchers over lists.
There is a feature request for this on https://github.com/hamcrest/JavaHamcrest/issues/388
The easiest option I think is to do something like this:
@Test
public void test() {
Map<String, Object> map1 = new HashMap<>();
map1.put("foo1", "foo1");
map1.put("foo2", Arrays.asList("foo2", "bar2"));
assertThat(map1, hasEntry("foo1", "foo1"));
assertThat(map1, hasListEntry(is("foo2"), containsInAnyOrder("foo2", "bar2")));
}
@SuppressWarnings("unchecked")
public static org.hamcrest.Matcher<java.util.Map<String, Object>> hasListEntry(org.hamcrest.Matcher<String> keyMatcher, org.hamcrest.Matcher<java.lang.Iterable<?>> valueMatcher) {
Matcher mapMatcher = org.hamcrest.collection.IsMapContaining.<String, List<?>>hasEntry(keyMatcher, valueMatcher);
return mapMatcher;
}
hasListEntry
is here only to prevent the compiler error. It does unchecked assignment that's why you need @SuppressWarnings("unchecked"). You can put this static method in your common test util for example.
Answered By - medvedev1088
Answer Checked By - Timothy Miller (JavaFixing Admin)