Search code examples
javagenericsjunithamcrest

Using generic bounded wildcards when testing Maps with junit


I'm trying to understand why this junit assertion is giving me a compile time error:

Map<String, Set<String>> actual = methodToTest();
assertThat(result, hasEntry("foo", new HashSet<String>(Arrays.asList("bar"))));

If I write it this way it works fine:

Map<String, Set<String>> actual = methodToTest();
Set<String> expected = new HashSet<String>(Arrays.asList("bar"));
assertThat(result, hasEntry("foo", expected));

The compiler error from the first example is:

The method assertThat(T, Matcher<? super T>) in the type Assert is not
applicable for the arguments (Map<String,Set<String>>, Matcher<Map<?
extends String,? extends HashSet<String>>>)

HashSet<String> is a subtype of Set<String> so why isn't this working?


Solution

  • HashSet<String> is a subtype of Set<String> true.

    However, Matcher<Map<String,HashSet<String>>> is not a subset of Matcher<Map<String,Set<String>>>. Remember that a List<String> is not a subtype of List<Object>.

    The assertThat method expects an argument of type Matcher<? super Map<String, Set<String>>> which is incompatibe with Matcher<Map<String,HashSet<String>>>.