在我的测试中我有以下几行:
when(client.runTask(anyString(), anyString(), isA(Iterable.class)).thenReturn(...)
isA(Iterable.class)
会产生警告,表示需要取消选中转换才能符合Iterable<Integer>
。这是什么语法?
isA(Iterable<Integer>.class)
isA((Iterable<Integer>)Iterable.class
不起作用。
有什么建议吗?
答案 0 :(得分:28)
是的,这是Mockito / Hamcrest的普遍问题。通常,将isA()
与泛型类一起使用会产生警告。
对于最常见的通用类,存在预定的Mockito匹配器:anyList(),anyMap()
,anySet()
和anyCollection()
。
建议:
Mockito 2.1.0中的Mockito 2.1.0添加了一个新的anyIterable()方法来匹配Iterables:
when(client.runTask(anyString(), anyString(), anyIterable()).thenReturn(...)
如果你只想摆脱Eclipse中的警告。自Eclipse Indigo以来存在选项:
窗口&gt;偏好&gt; Java&gt;编译器&gt;错误/警告&gt;通用 类型&gt;忽略不可避免的泛型类型问题
如果您只遇到一次问题,我建议您这样做。我个人不记得曾经需要isA(Iterable.class)
。
正如Daniel Pryden所说,您可以将@SuppressWarnings
限制为局部变量或辅助方法。
这解决了这个问题。但它有两个缺点:
TypeToken
类的库有额外的依赖关系。在这里,我使用了TypeToken class from Guava。 Gson中还有一个TypeToken
类,JAX-RS中有一个GenericType
。使用通用匹配器:
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());
}
}
答案 1 :(得分:7)
这就是我的所作所为:
// 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
答案 2 :(得分:3)
您可以在语句上方添加@SuppressWarnings("unchecked")
。没有其他办法,但如果它困扰你,你可以将演员阵容移动到辅助方法。
答案 3 :(得分:2)
没有办法做到这一点。为简化起见,您无法在不发出警告的情况下初始化此变量:
Class<Iterable<Integer>> iterableIntegerClass = ?
一种解决方案可能是使用pseudo-typedef antipattern,
,您创建并使用IntegerIterable
界面
interface IntegerIterable extends Iterable<Integer> {}
然后
isA(IntegerIterable.class)
将不再发出警告。但是你必须扩展实现Iterable
的类,让它们实现IntegerIterable
:)例如:
public class IntegerArrayList extends ArrayList<Integer> implements IntegerIterable {}
嗯好吃......
所以,我会鼓励你考虑通过添加你的方法来解决问题:
@SuppressWarnings("unchecked")