I have a dependency with a method that takes a Map as an argument.
public interface Service {
void doSomething(Map<String, String> map);
}
I'd like to write an assertion that this dependency is called with appropriate map contents. Something like this:
@RunWith(JMock.class)
public class MainTest {
private Mockery context = new Mockery();
private Service service = context.mock(Service.class);
private Main main = new Main(service);
@Test
public void test() {
context.checking(new Expectations(){{
oneOf(service).doSomething(with(hasEntry("test", "test")));
}});
main.run();
}
}
Unfortunately, this fails to compile, since hasEntry has wildcards in map generic parameters:
public static <K, V> org.hamcrest.Matcher<java.util.Map<? extends K, ? extends V>> hasEntry(K key, V value);
Is there any way to write a JMock expectaion for map contents?
There isn't a good answer to this as we hit the limits of Java generics. There's a tension between the generics we need for jMock and what we need for assertThat()
I tend to add a helper method, with an expressive name, to force the types.
@Test public void test() {
context.checking(new Expectations(){{
oneOf(service).doSomething(with(mapIncluding("test", "test")));
}});
main.run();
}
@SuppressWarnings({"unchecked", "rawtypes"})
private Matcher<Map<String, String>> mapIncluding(String key, String value) {
return (Matcher)Matchers.hasEntry(key, value);
};
Yes, this is pig-ugly. I can only apologise that this is the best we appear to be able to do. That said, it's rare that I have to go as far as turning off the types, I can give it a name that's meaningful in the domain, and I've localised the unchecking to the helper method.