With the new Assert grammar, when testing for identity, one would write
Assert.assertThat(obj1, CoreMatchers.sameInstance(obj2))
instead of
Assert.assertSame(obj1, obj2)
I am trying assert the identity of a map. So I write
Assert.assertThat(map1, CoreMatchers.sameInstance(map2))
where map is of type HashMap<String,String>
But my tests fail at compile time:
Error:(33, 9) error: no suitable method found for assertThat(Map,Matcher<Map<String,String>>)
method Assert.<T#1>assertThat(String,T#1,Matcher<? super T#1>) is not applicable
(cannot infer type-variable(s) T#1
(actual and formal argument lists differ in length))
method Assert.<T#2>assertThat(T#2,Matcher<? super T#2>) is not applicable
(cannot infer type-variable(s) T#2
(argument mismatch; Matcher<Map<String,String>> cannot be converted to Matcher<? super Map>))
where T#1,T#2 are type-variables:
T#1 extends Object declared in method <T#1>assertThat(String,T#1,Matcher<? super T#1>)
T#2 extends Object declared in method <T#2>assertThat(T#2,Matcher<? super T#2>)
Error:(33) error: no suitable method found for assertThat(Map,Matcher<Map<String,String>>)
Why can't JUnit (or Hamcrest) figure out which matcher to use?
Turns out this had nothing to do with asserting the identity of the map - the code was correct - but it does have something to do with generics.
The class I was trying to test looked something like this:
public class Response<T>{
public final Map<String, String> map;
public final T data;
}
However, the test was written like this:
@Test
public void testStuff() throws Exception {
Map<String, String> map = new HashMap<>();
Object data = new Object();
Response target = new Response<>(map, data);
assertThat(target.map, sameInstance(map));
assertThat(target.data, sameInstance(data));
}
The compilation error is actually at the last line, because T is unknown (<?>)
to the compiler, it couldn't find an appropriate matcher. I fixed the test by declaring the raw type.
@Test
public void testStuff() throws Exception {
Map<String, String> map = new HashMap<>();
Object data = new Object();
Response<Object> target = new Response<>(map, data);
assertThat(target.map, sameInstance(map));
assertThat(target.data, sameInstance(data));
}
But I find it odd why the compiler complains about the previous line...