我有两个类Generic<T, R>
的通用对象:
Generic<TypeA, TypeB> genericOne;
Generic<TypeB, TypeC> genericTwo;
我必须嘲笑:
when(someObject.someMethod(Matchers.<Generic<TypeA, TypeB>>any()))
.thenReturn(responseOne());
when(someObject.someMethod(Matchers.<Generic<TypeB, TypeC>>any()))
.thenReturn(responseTwo());
问题是,由于类型擦除,mockito不会看到这两个方法调用之间的区别 - 它都被识别为Generic<T, R>
类。
有没有办法区分这两种方法调用?
答案 0 :(得分:2)
Mockito并不知道在any()
调用之前指定了哪些泛型,无论如何它并不重要。
模拟行为记录中预期的参数必须依赖:
equals()
equals()
不充分,则以捕获者为准any()
如果模拟调用中的参数值在测试夹具中不重要或不知道这些永远不必依赖于指定的泛型。
要有一个好例子,请查看Mockito.anyCollectionOf(Class<T> clazz)
或Mockito.anyMapOf(Class<K> keyClazz, Class<V> valueClazz)
。
这些方法知道传递的类,但无论如何,它们的规范都说明了:
此方法不进行任何类型检查,只有避免 在代码中强制转换。然而,这可能会改变(类型检查可能会 在未来的主要版本中添加)。
一般来说,您要检查的是使用期望参数调用模拟方法而不是任何参数:因此any()
永远不会实现它。
因此,尝试仅检查泛型类型,但接受任何值作为参数似乎是反模式嘲弄。
在您的情况下,如果equals()
不便于when()
录音中的匹配,请将Mockito捕手与verify()
一起使用,并在执行模拟后进行检查。
答案 1 :(得分:1)
我不认为可以区分两者,因为通用类型已被删除。但还有其他选择。
您可以将此次调用与特定订单相结合,这样即使mockito无法区分它们,它也会返回预期值。这是通过链接thenReturn
方法完成的。第一次调用返回responseOne()
,第二次调用返回responseTwo()
。
when(someObject.someMethod(Matchers.<Generic<TypeA, TypeB>>any()))
.thenReturn(responseOne())
.thenReturn(responseTwo());
但这并不是最佳选择,因为如果您的实施发生变化,此测试将会中断。所以这是第二种选择。
您可以为此对象实现自定义Fake。这样你就可以更好地控制这个实例的行为方式。例如。
class SomeObjectFake {
private final SomeResponse response;
public SomeObject(SomeResponse response) {
this.response = response;
}
public SomeResponse someMethod(Generic<TypeA, TypeB> arg) {
// Decide what to return
return response;
}
}