Mockito:试图窥探方法是调用原始方法
我正在使用Mockito 1.9.0。 我想在JUnittesting中模拟一个类的单一方法的行为,所以我有
final MyClass myClassSpy = Mockito.spy(myInstance); Mockito.when(myClassSpy.method1()).thenReturn(myResults);
问题是,在第二行, myClassSpy.method1()
实际上被调用,导致一个exception。 我使用mock的唯一原因是,以后只要myClassSpy.method1()
,真正的方法将不会被调用,并且myResults
对象将被返回。
MyClass
是一个接口, myInstance
是一个实现,如果这很重要。
我需要做些什么来纠正这种间谍行为?
让我引用官方文档 :
关于间谍真相的重要窍门!
有时使用(对象)来扼杀间谍是不可能的。 例:
List list = new LinkedList(); List spy = spy(list); //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) when(spy.get(0)).thenReturn("foo"); //You have to use doReturn() for stubbing doReturn("foo").when(spy).get(0);
在你的情况下,它是这样的:
doReturn(resulstIWant).when(myClassSpy).method1();
我的情况与接受的答案不同。 我试图嘲笑一个包没有生活的实例的包私有方法
package common; public class Animal { void packageProtected(); } package instances; class Dog extends Animal { }
和testing类
package common; public abstract class AnimalTest<T extends Animal> { @Before setup(){ doNothing().when(getInstance()).packageProtected(); } abstract T getInstance(); } package instances; class DogTest extends AnimalTest<Dog> { Dog getInstance(){ return spy(new Dog()); } @Test public void myTest(){} }
编译是正确的,但是当它试图设置testing时,它调用真正的方法。
声明受保护或公开的方法修复了这个问题,但这不是一个干净的解决scheme。
托马斯·努尔凯维奇(Tomasz Nurkiewicz)的回答似乎并没有说出整个故事!
NB Mockito版本:1.10.19。
我是一个Mockito新手,所以不能解释以下行为:如果有专家可以改善这个答案,请随时。
这里讨论的方法getContentStringValue
不是 final
,也不是static
。
这行确实调用了原始方法getContentStringValue
:
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));
这行不会调用原始方法getContentStringValue
:
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));
由于我无法回答的原因,使用isA()
导致doReturn
的预期(?)“不调用方法”行为失败。
让我们看看这里涉及的方法签名:它们都是Matchers
static
方法。 Javadoc都说这两个返回null
,这本身有点困难。 大概是Class
对象作为参数被传递,但是结果要么从不计算,要么被抛弃。 鉴于null
可以代表任何类,并且你希望被调用的方法不被调用,所以isA( ... )
和any( ... )
的签名不能返回null
而不是generics参数* <T>
?
无论如何:
public static <T> T isA(java.lang.Class<T> clazz) public static <T> T any(java.lang.Class<T> clazz)
API文档没有提供任何线索。 这似乎也表示,对这种“不叫方法”行为的需求是“非常罕见的”。 就我个人而言,我一直都在使用这种技巧:通常我会发现嘲笑涉及到“设置场景”的几行……然后调用一个方法,然后在您已经上演的模拟上下文中“播放”场景。当你设置风景和道具的时候,你想要的最后一件事就是让演员们进入舞台,开始表演他们的心灵。
但是这超出了我的薪水等级…我邀请任何经过的Mockito高级牧师的解释…
*是“通用参数”的正确术语?
在我的情况下,使用Mockito 2.0,我必须将所有的any()参数改为nullable(),以便存根真实的调用。