我依赖一个接受Map作为参数的方法。
public interface Service {
void doSomething(Map<String, String> map);
}我想写一个断言,这个依赖是用适当的map内容调用的。如下所示:
@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();
}
}不幸的是,这无法编译,因为hasEntry在地图通用参数中有通配符:
public static <K, V> org.hamcrest.Matcher<java.util.Map<? extends K, ? extends V>> hasEntry(K key, V value);有没有办法为地图内容写一个JMock期望?
发布于 2012-05-28 17:31:52
这个问题没有一个好的答案,因为我们已经达到了Java泛型的极限。在jMock所需的泛型和assertThat()所需的泛型之间存在着矛盾。
我倾向于添加一个帮助器方法,使用一个富有表现力的名称来强制类型。
@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);
};是的,这是猪的丑陋。我只能道歉,这似乎是我们所能做的最好的事情。也就是说,我很少需要关闭类型,我可以给它一个在域中有意义的名称,并且我已经本地化了对helper方法的取消检查。
发布于 2012-06-16 20:30:32
我最终创建了一个方法specify(),它允许将通用匹配器向下转换为更具体的匹配器
public static <T> Matcher<T> specify(final Matcher<? super T> matcher) {
return new TypeSafeMatcher<T>() {
@Override
protected boolean matchesSafely(T item) {
return matcher.matches(item);
}
@Override
public void describeTo(Description description) {
matcher.describeTo(description);
}
};
}使用这个方法,我可以向下转换任何现有的泛型匹配器,比如hasEntry()
public <K, V> Matcher<Map<? extends K, ? extends V>> hasEntry(K key, V value)以通用安全的方式转换为更具体的类型,如下所示:
private static <K,V> Matcher<Map<K, V>> aMapHavingEntry(K key, V value) {
return specify(hasEntry(key, value));
}现在我可以使用这个特定的匹配器作为期望参数:
context.checking(new Expectations() {{
oneOf(service).doSomething(with(aMapHavingEntry("test", "test")));
}});使用specify()方法,我为最流行的接口创建了一组特定的匹配器: Map、Collection、List、Set,如下所示:
private static <K,V> Matcher<Map<K, V>> aMapHavingEntry(K key, V value) {
return specify(hasEntry(key, value));
}
private static <K> Matcher<Collection<K>> aCollectionContainingInAnyOrder(K... items) {
return specify(containsInAnyOrder(items));
}我还建议给JMock添加同样的功能,尽管我得到的只是静默。
https://stackoverflow.com/questions/10704443
复制相似问题