在我的测试中,我有以下行:
when(client.runTask(anyString(), anyString(), isA(Iterable.class)).thenReturn(...)
isA(Iterable.class)
产生警告,它需要转换选中以符合Iterable<Integer>
。 什么是语法是什么?
isA(Iterable<Integer>.class)
isA((Iterable<Integer>)Iterable.class
不工作。
有什么建议?
的Mockito / Hamcrest和泛型类
是的,这是的Mockito / Hamcrest一个普遍的问题。 一般采用isA()
与泛型类产生一个警告。
有predifined匹配器的Mockito为最常用的通用类: anyList() , anyMap()
anySet()
和anyCollection()
建议:
anyIterable()在2.1.0的Mockito
2.1.0的Mockito添加了新anyIterable()匹配Iterables方法:
when(client.runTask(anyString(), anyString(), anyIterable()).thenReturn(...)
忽略在Eclipse
如果你只是想摆脱在Eclipse的警告。 因为选项存在的Eclipse靛蓝 :
窗口>首选项>的Java>编译器>错误/警告>泛型类型>忽略不可避免的通用类型问题
快速修复与@SuppressWarnings
我建议你做这个,如果你有问题只有一次。 我个人不记得曾经需要一个isA(Iterable.class)
正如丹尼尔Pryden说,你可以限制@SuppressWarnings
局部变量或辅助方法。
使用带有TypeToken通用ISA()匹配
这解决了这个问题为好。 但它有两个缺点:
- 语法是不是太漂亮,可能会混淆一些人。
- 您对库提供一个额外的依赖
TypeToken
类。 这里我用了TypeToken类番石榴 。 还有一个TypeToken
在GSON类和GenericType
在JAX-RS。
使用通用的匹配:
import static com.arendvr.matchers.InstanceOfGeneric.isA;
import static org.mockito.ArgumentMatchers.argThat;
// ...
when(client.runTask(anyString(), anyString(), argThat(isA(new TypeToken<Iterable<Integer>>() {}))))
.thenReturn(...);
通用匹配类:
package com.arendvr.matchers;
import com.google.common.reflect.TypeToken;
import org.mockito.ArgumentMatcher;
public class InstanceOfGeneric<T> implements ArgumentMatcher<T> {
private final TypeToken<T> typeToken;
private InstanceOfGeneric(TypeToken<T> typeToken) {
this.typeToken = typeToken;
}
public static <T> InstanceOfGeneric<T> isA(TypeToken<T> typeToken) {
return new InstanceOfGeneric<>(typeToken);
}
@Override
public boolean matches(Object item) {
return item != null && typeToken.getRawType().isAssignableFrom(item.getClass());
}
}
这是我做的:
// Cast from Class<Iterable> to Class<Iterable<Integer>> via the raw type.
// This is provably safe due to erasure, but will generate an unchecked warning
// nonetheless, which we suppress.
@SuppressWarnings("unchecked")
Class<Iterable<Integer>> klass
= (Class<Iterable<Integer>>) (Class) Iterable.class;
// later
isA(klass) // <- now this is typesafe
您可以添加@SuppressWarnings("unchecked")
上面的语句。 没有别的办法,但如果你烦恼,你可以移动要转换成一个辅助方法。
有没有办法做到这一点。 为了简化,你不能没有警告初始化这个变量:
Class<Iterable<Integer>> iterableIntegerClass = ?
一种解决方案是使用伪typedef的反模式 ,您创建和使用IntegerIterable
接口
interface IntegerIterable extends Iterable<Integer> {}
然后
isA(IntegerIterable.class)
将不再产生报警。 但是,你将不得不扩展类实现Iterable
让他们实现IntegerIterable
:)例如:
public class IntegerArrayList extends ArrayList<Integer> implements IntegerIterable {}
嗯美味...
所以,我会sugest您通过添加到您的方法来考虑刚过裂缝纸:
@SuppressWarnings("unchecked")