我试图将我的模拟存根如下,
when(someMock.someMethod(Matchers.<SomeInterface<MyType>> any()).thenReturn(someValue);
和
when(someMock.someMethod(Matchers.<SomeInterface<Map<String,Boolean>>> any()).thenReturn(someOtherValue);
我注意到第二个存根正在覆盖第一个存根。因此,即使我致电someOtherValue
someMock.someMethod(new SomeInterfaceImplementation());
我不确定这里缺少什么。我尝试通过Mockito文档查看这个特定用例,但我没有找到任何东西。
非常感谢任何帮助/指示。
答案 0 :(得分:3)
由于类型擦除,Mockito将无法在运行时确定传递给SomeInterface<T>
的{{1}}实例的泛型参数。对someMock.someMethod
的任何调用似乎都是使用someMethod
的实例进行的,没有通用参数。
Matchers的JavaDoc通过警告暗示了这个问题(尽管它没有解释原因):
任何家庭方法都不进行任何类型检查,这些只是为了避免在您的代码中进行投射。如果要执行类型检查,请使用isA(Class)方法。但是,这可能会在未来的主要版本中发生变化(可以添加类型检查)。
还有其他一些辅助方法,如anyListOf
,它们似乎处理了集合的通用参数,但这些方法只是为了方便而存在,并且实际上不会检查泛型类型:
anyList()的通用友好别名。它可以替代@SuppressWarnings(&#34;未经检查&#34;)以保持代码清除编译器警告。
任何列表或null。
此方法不进行任何类型检查,只是为了避免在您的代码中进行转换。但是,这可能会在未来的主要版本中发生变化(可以添加类型检查)。
由于SomeInterface
匹配器将匹配任何对象而不管类型和通用参数如何,因此使用any()
对when()
的第二次调用将覆盖第一个。解决此问题的唯一方法是仅对两种类型的调用调用any()
,并进行某种运行时检查以确定结果应该是什么(例如,在传递给when(...)
的{{1}}中Answer
)。
例如,假设我们想要模拟以下类(不值得嘲笑,但请耐心等待):
thenAnswer
public class SomeClass {
public <T> T getFirst(List<T> list) {
return list.get(0);
}
}
方法与您的类有同样的问题,因为使用getFirst
/ any
/ isA
/ anyList
匹配器将无法区分anyListOf
和List<String>
。
以下是使用List<Integer>
模仿此内容的一种方法:
andAnswer
这非常难看,根据你的实际泛型类型的使用方式,它可能很难实现,但我相信这是在运行时避免泛型类型信息的唯一方法。