的Mockito:试图刺探方法调用原始的方法(Mockito: Trying to spy on m

2019-06-17 12:30发布

我使用的是1.9.0的Mockito。 我想嘲笑为JUnit测试类的一个方法的行为,所以我有

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

问题是,在第二行中, myClassSpy.method1()实际上是获取调用,产生一个异常。 我用嘲笑的唯一原因是这样,以后,每当myClassSpy.method1()被调用时,真正的方法将不会被调用,而myResults对象将被退回。

MyClass是一个接口, myInstance就是一个很好的执行,如果该事项。

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

Answer 1:

让我引用官方文档 :

重要疑难杂症上刺探真实的物体!

有时是不可能的磕碰间谍时(对象)来使用。 例:

 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();


Answer 2:

我的情况是从接受的答案不同。 我试图嘲弄为没有生活在那个包实例的包私有方法

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

编译是正确的,但是当它试图安装测试,它会调用真正的方法来代替。

声明方法保护的公共的修复问题,寿它不是一个干净的解决方案。



Answer 3:

由托马斯Nurkiewicz答案似乎不告诉整个故事!

NB版本的Mockito:19年1月10日。

我不能不说是一个福利局的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失败。

让我们来看看这里所涉及的方法签名:它们都是static的方法Matchers 。 两者都是由Javadoc中说要回null ,这是一个有点难以在自身周围让你的头。 想必Class作为参数传递的对象进行检查,但结果或者从未计算或丢弃。 鉴于null可以代表任何类和你希望的模拟的方法不被调用,能不签名isA( ... )any( ... )只返回null ,而不是一个泛型参数* <T>

无论如何:

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

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

API文档没有给出这方面有任何的线索。 这也似乎在说需要这样的“不叫法”的行为是“非常罕见”。 我个人使用这种技术的所有时间 :通常我发现嘲讽涉及的几行其中“设置场景” ......随后调用,然后将你所上演的模拟情境“中扮演了”现场的方法.. 。而当你建立风景和道具你想要的最后一件事是为演员进入舞台左侧,并开始行动,他们的心...

但是,这是远远超出我的薪酬等级......我邀请任何通过高的Mockito牧师解释...

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



Answer 4:

在我的情况下,使用2.0的Mockito,我不得不改变所有的任何()的参数可以为空(),以存根实际通话。



Answer 5:

这可能导致与间谍问题的一个更可能的情况是,当你正在测试春天豆类 (带弹簧的测试框架),与测试过程中代理方式的物体一些其他的框架

@Autowired
private MonitoringDocumentsRepository repository

void test(){
    repository = Mockito.spy(repository)
    Mockito.doReturn(docs1, docs2)
            .when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}

在上面的代码与Spring和会的Mockito尝试代理你的MonitoringDocumentsRepository对象,但春天将是第一个,这将导致findMonitoringDocuments方法的实际通话。 如果我们只是把间谍库对象后调试我们的代码它看起来像这里面的调试器:

repository = MonitoringDocumentsRepository$$EnhancerBySpringCGLIB$$MockitoMock$

@SpyBean救援

相反,如果@Autowired我们使用注解@SpyBean注释,我们会解决上述问题,SpyBean注释也将注入资源库对象,但它会被的Mockito首先代理和看起来像这里面的调试器

repository = MonitoringDocumentsRepository$$MockitoMock$$EnhancerBySpringCGLIB$

这里是代码:

@SpyBean
private MonitoringDocumentsRepository repository

void test(){
    Mockito.doReturn(docs1, docs2)
            .when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}


Answer 6:

我找到了另一个理由间谍调用原始方法。

有人有想法嘲笑一个final类,并且发现了大约MockMaker

由于这种工作方式不同,以我们目前的机制,这其中有不同的限制,当我们要积累经验和用户反馈,该功能必须明确激活可用; 它可以通过扩展的Mockito机构通过创建文件来完成src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker :包含单一线mock-maker-inline

来源: https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#mock-the-unmockable-opt-in-mocking-of-final-classesmethods

我合并,并把该文件到我的机器后,我的测试中失败了。

我不得不删除行(或文件), spy()工作。



Answer 7:

确保一个从类没有调用的方法的一种方法是重写与虚拟的方法。

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


Answer 8:

答斯卡拉用户:即使把doReturn第一不起作用! 见这个职位 。



文章来源: Mockito: Trying to spy on method is calling the original method