我使用的是Mockito 1.9.0。我想在JUnit测试中模拟类的单个方法的行为,所以我有

final MyClass myClassSpy = Mockito.spy(myInstance);
Mockito.when(myClassSpy.method1()).thenReturn(myResults);

问题是,在第二行中,myClassSpy.method1()实际上被调用了,导致了一个异常。我使用模拟的唯一原因是,以后无论何时调用myClassSpy.method1(),都不会调用真正的方法,并且将返回myResults对象。

MyClass是一个接口,myInstance是它的实现。

我需要做什么来纠正这种间谍行为?


当前回答

你侦察真实物体的能力很重要

当使用间谍存根一个方法时,请使用doReturn()方法族。

when(Object)将导致调用可以抛出异常的实际方法。

List spy = spy(new LinkedList());

//Incorrect , spy.get() will throw IndexOutOfBoundsException   
 when(spy.get(0)).thenReturn("foo");

//You have to use doReturn() for stubbing    
doReturn("foo").when(spy).get(0);

其他回答

让我引用官方文件:

重要的是,你在监视真实的物体! 有时候不可能使用when(Object)来攻击间谍。例子: List List = new LinkedList(); List spy =间谍(列表); //不可能:real方法被调用,所以spy.get(0)抛出IndexOutOfBoundsException(列表仍然为空) 当(spy.get (0)) .thenReturn (" foo "); //你必须使用doReturn()进行存根 doReturn(“foo”)当(间谍). get (0);

在你的情况下,它是这样的:

doReturn(resultsIWant).when(myClassSpy).method1();

有点晚了,但以上的解决方案并不适合我,所以分享我的0.02美元

Mokcito版本:1.10.19

MyClass.java

private int handleAction(List<String> argList, String action)

Test.java

MyClass spy = PowerMockito.spy(new MyClass());

以下没有为我工作(实际的方法正在被调用):

1.

doReturn(0).when(spy , "handleAction", ListUtils.EMPTY_LIST, new String());

2.

doReturn(0).when(spy , "handleAction", any(), anyString());

3.

doReturn(0).when(spy , "handleAction", null, null);

以下工作:

doReturn(0).when(spy , "handleAction", any(List.class), anyString());

Tomasz Nurkiewicz的回答似乎并没有说出全部的故事!

NB模仿版本:1.10.19。

我是一个非常多的Mockito新手,所以不能解释以下行为:如果有一个专家在那里谁可以改善这个答案,请随意。

这里讨论的方法getContentStringValue不是最终的,也不是静态的。

这一行调用了原始方法getContentStringValue:

doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));

这一行不调用原始方法getContentStringValue:

doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));

由于我无法回答的原因,使用isA()会导致预期的(?)doReturn的“不调用方法”行为失败。

Let's look at the method signatures involved here: they are both static methods of Matchers. Both are said by the Javadoc to return null, which is a little difficult to get your head around in itself. Presumably the Class object passed as the parameter is examined but the result either never calculated or discarded. Given that null can stand for any class and that you are hoping for the mocked method not to be called, couldn't the signatures of isA( ... ) and any( ... ) just return null rather than a generic parameter* <T>?

无论如何:

public static <T> T isA(java.lang.Class<T> clazz)

public static <T> T any(java.lang.Class<T> clazz)

The API documentation does not give any clue about this. It also seems to say the need for such "do not call method" behaviour is "very rare". Personally I use this technique all the time: typically I find that mocking involves a few lines which "set the scene" ... followed by calling a method which then "plays out" the scene in the mock context which you have staged... and while you are setting up the scenery and the props the last thing you want is for the actors to enter stage left and start acting their hearts out...

但这远远超出了我的职权范围…我请路过的Mockito大祭司解释一下…

*“通用参数”是正确的术语吗?

我的情况与公认的答案不同。我试图模拟一个包私有方法的实例,该实例不在该包中

package common;

public class Animal {
  void packageProtected();
}

package instances;

class Dog extends Animal { }

测试类

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(){}
}

编译是正确的,但是当它试图设置测试时,它反而调用了真正的方法。

将方法声明为protected或public可以修复该问题,但这并不是一个干净的解决方案。

你侦察真实物体的能力很重要

当使用间谍存根一个方法时,请使用doReturn()方法族。

when(Object)将导致调用可以抛出异常的实际方法。

List spy = spy(new LinkedList());

//Incorrect , spy.get() will throw IndexOutOfBoundsException   
 when(spy.get(0)).thenReturn("foo");

//You have to use doReturn() for stubbing    
doReturn("foo").when(spy).get(0);