我试图模拟对我的一个类的受保护方法的调用:
import com.couchbase.client.java.view.Stale; // an enum
import com.google.common.base.Optional;
public class MyClass {
public List<String> myList(Optional<Integer> arg1, Optional<Stale> arg2) {
...
}
}
模拟应按以下方式完成:
// Providing types for any() does not change anything
Mockito.when(myClass.myList(Mockito.any(), Mockito.any()).thenReturn(new ArrayList());
每当执行前一行时,都会调用实际的 myList()
方法,arg1
和 arg2
的空值。为什么叫这种方法呢?毕竟,我试图避免任何处决...
正如Brice所提到的,如果你的myList
方法是最终的,那么Java会跳过虚拟方法调度,并调用原始对象(而不是你的模拟)。
如果您正在监视实际类,则预期的行为是when
将实际对象作为存根的一部分调用:毕竟,在表达式中when(foo.bar())
Java对when
并假设它关心foo.bar()
的返回值)没有任何特殊之处,而不是调用本身。(我将在此处回答的"实现详细信息"部分中介绍存根过程。
此语法更适合间谍:
doReturn(new ArrayList()).when(myClass).myList(any(), any());
由于此不同的 when
方法接收对象,因此 Mockito 可以将对象准备为在存根期间不执行任何操作,从而避免对 myList
方法进行任何虚假调用。
虽然杰夫的回答没有显示我问题的解决方法,但它为我指明了正确的方向。
将嘲笑行为更改为doReturn...
后,我突然收到一条错误消息。这条消息告诉我,myClass
不是有意义的模拟,因为你只能模拟(或存根?)模拟或监视对象的方法。因此,正如 Jeff 的答案所示,并在 mockito 的文档中进行了解释,我创建了一个部分模拟MyClass
MyClass myClass = Mockito.spy(new MyClass());
有了这个部分的模拟,杰夫的方法嘲笑突然奏效了(我的仍然没有,因此应该避免)。
所以:谢谢你,杰夫!