Java Mockito:试图监视方法正在调用原始方法

Java Mockito:试图监视方法正在调用原始方法,java,junit,mockito,Java,Junit,Mockito,我正在使用Mockito 1.9.0。我希望在JUnit测试中模拟类的单个方法的行为,因此 final MyClass myClassSpy = Mockito.spy(myInstance); Mockito.when(myClassSpy.method1()).thenReturn(myResults); 问题是,在第二行中,myClassSpy.method1()实际上被调用,导致异常。我使用mock的唯一原因是,以后无论何时调用myClassSpy.method1(),都不会调用真正的

我正在使用Mockito 1.9.0。我希望在JUnit测试中模拟类的单个方法的行为,因此

final MyClass myClassSpy = Mockito.spy(myInstance);
Mockito.when(myClassSpy.method1()).thenReturn(myResults);
问题是,在第二行中,
myClassSpy.method1()
实际上被调用,导致异常。我使用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(resultsIWant).when(myClassSpy).method1();
让我引述:

重要的是,我已经掌握了监视真实物体的方法! 有时,当(对象)用于刺杀间谍时,是不可能的。例如:

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(resultsIWant).when(myClassSpy).method1();

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

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(){}
}
包通用;
公共抽象类动物测试{
@以前
设置(){
doNothing().when(getInstance()).packageProtected();
}
抽象T getInstance();
}
包实例;
类DogTest扩展了AnimalTest{
Dog getInstance(){
返回间谍(新狗());
}
@试验
public void myTest(){}
}
编译是正确的,但是当它试图设置测试时,它会调用real方法


声明该方法受保护或公开可以修复问题,尽管它不是一个干净的解决方案。

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

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(){}
}
包通用;
公共抽象类动物测试{
@以前
设置(){
doNothing().when(getInstance()).packageProtected();
}
抽象T getInstance();
}
包实例;
类DogTest扩展了AnimalTest{
Dog getInstance(){
返回间谍(新狗());
}
@试验
public void myTest(){}
}
编译是正确的,但是当它试图设置测试时,它会调用real方法


宣布该方法受保护或公开解决了这个问题,尽管这不是一个干净的解决方案。

托马兹·努尔基维茨的回答似乎并没有说明全部情况

NB Mockito版本:1.10.19

我是一个莫基托新手,所以无法解释以下行为:如果有专家可以改进这个答案,请放心

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

此行调用原始方法
getContentStringValue

doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));
此行不调用原始方法
getContentStringValue

doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));
出于我无法回答的原因,使用
isA()
会导致
doReturn
的预期(?“不要调用方法”行为失败

让我们看看这里涉及的方法签名:它们都是
匹配器的
静态方法。Javadoc说这两个函数都返回
null
,这本身就有点难理解。假定检查作为参数传递的
对象,但结果从未计算或丢弃。鉴于
null
可以代表任何类,并且您希望模拟方法不会被调用,那么
isA(…)
any(…)
的签名不能只返回
null
而不是泛型参数*

无论如何:

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

public static <T> T any(java.lang.Class<T> clazz)
publicstatictisa(java.lang.Class clazz)
公共静态T any(java.lang.Class clazz)
API文档没有给出任何关于这方面的线索。它似乎还说,这种“不调用方法”行为的必要性“非常罕见”。就我个人而言,我一直都在使用这种技巧:我发现模仿通常包括几句“设置场景”的台词。。。然后调用一个方法,该方法将“播放”已上演的模拟上下文中的场景。。。当你在设置布景和道具的时候,你最不想看到的就是演员们从左边进入舞台,开始表演他们的心

但这远远超出了我的工资等级。。。我请任何路过的莫基托大祭司解释


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

托马兹·努尔基维茨的答案似乎并没有说明全部情况

NB Mockito版本:1.10.19

我是一个莫基托新手,所以无法解释以下行为:如果有专家可以改进这个答案,请放心

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

此行调用原始方法
getContentStringValue

doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));
此行不调用原始方法
getContentStringValue

doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));
出于我无法回答的原因,使用
isA()
会导致
doReturn
的预期(?“不要调用方法”行为失败

让我们看看这里涉及的方法签名:它们都是
匹配器的
静态方法。Javadoc说这两个函数都返回
null
,这本身就有点难理解。假定检查作为参数传递的
对象,但结果从未计算或丢弃。假设
null
可以代表任何类,并且您是
doReturn(0).when(spy , "handleAction", any(List.class), anyString());