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

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

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

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

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


当前回答

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

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可以修复该问题,但这并不是一个干净的解决方案。

其他回答

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

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可以修复该问题,但这并不是一个干净的解决方案。

确保不调用类中的方法的一种方法是使用dummy重写该方法。

    WebFormCreatorActivity activity = spy(new WebFormCreatorActivity(clientFactory) {//spy(new WebFormCreatorActivity(clientFactory));
            @Override
            public void select(TreeItem i) {
                log.debug("SELECT");
            };
        });

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

当使用间谍存根一个方法时,请使用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);

在我的例子中,使用Mockito 2.0,我必须将所有any()参数更改为nullable(),以便存根真正的调用。

正如在一些评论中提到的,我的方法是“静态的”(尽管是由类的实例调用的)

public class A {
  static void myMethod() {...}
}
A instance = spy(new A());
verify(instance).myMethod(); // still calls the original method because it's static

解决方法是创建一个实例方法,或者通过一些配置将Mockito升级到一个新版本:https://stackoverflow.com/a/62860455/32453