Mockito isA(Class clazz)如何解决类型安全问题?
在我的测试中我有以下几行:
when(client.runTask(anyString(), anyString(), isA(Iterable.class)).thenReturn(...)
isA(Iterable.class)
产生警告,它需要未经检查的转换以符合Iterable
。 这是什么语法?
isA(Iterable.class) isA((Iterable)Iterable.class
不工作。
有什么建议么?
Mockito / Hamcrest和generics课程
是的,这是Mockito / Hamcrest的普遍问题。 通常使用带有generics类的isA()
会产生警告。
对于最常见的generics类,存在预定的Mockito匹配器: anyList() , anyMap()
, anySet()
和anyCollection()
。
建议:
Mockito 2.1.0中的anyIterable()
Mockito 2.1.0添加了一个新的anyIterable()方法来匹配Iterables:
when(client.runTask(anyString(), anyString(), anyIterable()).thenReturn(...)
在Eclipse中忽略
如果你只想摆脱Eclipse中的警告。 自Eclipse Indigo以来存在选项:
窗口>首选项> Java>编译器>错误/警告>通用类型>忽略不可避免的generics类型问题
使用@SuppressWarnings快速修复
如果您只遇到一次问题,我建议您这样做。 我个人不记得曾经需要一个isA(Iterable.class)
。
正如Daniel Pryden所说,您可以将@SuppressWarnings
限制为局部变量或辅助方法。
使用带有TypeToken的通用isA()匹配器
这样可以很好地解决问题。 但它有两个缺点:
- 语法不太漂亮,可能会让一些人感到困惑。
- 您对提供
TypeToken
类的库有额外的依赖性。 在这里,我使用了Guava的TypeToken类 。 在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>() {})))) .thenReturn(...);
通用匹配器类:
package com.arendvr.matchers; import com.google.common.reflect.TypeToken; import org.mockito.ArgumentMatcher; public class InstanceOfGeneric implements ArgumentMatcher { private final TypeToken typeToken; private InstanceOfGeneric(TypeToken typeToken) { this.typeToken = typeToken; } public static InstanceOfGeneric isA(TypeToken typeToken) { return new InstanceOfGeneric<>(typeToken); } @Override public boolean matches(Object item) { return item != null && typeToken.getRawType().isAssignableFrom(item.getClass()); } }
这是我做的:
// Cast from Class to Class> via the raw type. // This is provably safe due to erasure, but will generate an unchecked warning // nonetheless, which we suppress. @SuppressWarnings("unchecked") Class> klass = (Class>) (Class) Iterable.class; // later isA(klass) // <- now this is typesafe
您可以在语句上方添加@SuppressWarnings("unchecked")
。 没有其他办法,但如果它困扰你,你可以将演员阵容移动到辅助方法。
没有办法做到这一点。 为简化起见,您无法在不发出警告的情况下初始化此变量:
Class> iterableIntegerClass = ?
一种解决方案可能是使用伪typedef反模式 ,您创建并使用IntegerIterable
接口
interface IntegerIterable extends Iterable {}
然后
isA(IntegerIterable.class)
将不再发出警告。 但是你必须扩展实现Iterable
的类,让它们实现IntegerIterable
:)例如:
public class IntegerArrayList extends ArrayList implements IntegerIterable {}
嗯好吃……
所以,我会鼓励你考虑通过添加到你的方法来解决问题:
@SuppressWarnings("unchecked")
- hibernate是否保留LinkedHashSet的顺序,如果是,如何?
- Java Reflection私有方法与参数最佳方法?
- wait / notify和wait / interrupt有什么区别?
- 在Java应用程序中处理版本号的好方法是什么?
- java.util.Arrays中的私有静态类ArrayList – 为什么?
- 一个在某个网站上搜索的java程序
- java.math.BigInteger无法强制转换为java.lang.Integer
- 如何关闭PDF文件以重新创建它? (正在使用的文件)
- NetConnection.Call.Failed偶尔在Flex3 / Tomcat / BlazeDS / Spring中发生