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(),以便存根真实的调用。