Mockito.when被覆盖的存根

时间:2014-07-07 16:56:06

标签: java mockito

我试图将我的模拟存根如下,

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文档查看这个特定用例,但我没有找到任何东西。

非常感谢任何帮助/指示。

1 个答案:

答案 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匹配器将无法区分anyListOfList<String>

以下是使用List<Integer>模仿此内容的一种方法:

andAnswer

这非常难看,根据你的实际泛型类型的使用方式,它可能很难实现,但我相信这是在运行时避免泛型类型信息的唯一方法。