同一类中的模拟方法

时间:2016-08-29 05:10:29

标签: java unit-testing mocking mockito

我正在使用Mockito来模拟我正在编写测试的同一个类中的方法。我在SO(Mocking method in the same class)上看到了其他答案,但可能是我误解了它们,因为我遇到了问题。

 class Temp() {

    public boolean methodA(String param) {

         try {

             if(methodB(param))
                   return true;

             return false;
         } catch (Exception e) {
               e.printStackTrace();
         }
    }
 }

我的测试方法:

 @Test
 public void testMethodA() {

    Temp temp = new Temp();
    Temp spyTemp = Mockito.spy(temp);

    Mockito.doReturn(true).when(spyTemp).methodB(Mockito.any()); 
    boolean status = temp.methodA("XYZ");

    Assert.assertEquals(true, status);
 }
然而,由于方法B的定义被执行,我打印出了预期。 我的理解是使用spyTemp来模拟methodB的定义。然而,情况似乎并非如此。

有人可以解释我哪里出错吗?

3 个答案:

答案 0 :(得分:13)

第一个问题是你必须使用spyTest对象来期待Mockito的东西。这与测试不一样。 spyTemp由Mockito对象temp包裹。

另一个问题是您只存根methodB(),但尝试运行methodA()。在您调用methodB()时methodA()的实施中是,但是您在this.methodB()拨打电话,而不是spyTemp.methodB()。在这里,您必须了解只有在temp的实例上调用时,模拟才会起作用。它由Mockito代理包裹,可以接听你的电话,如果你覆盖了一些方法,它会调用你的新实现而不是原始实现。但是,由于原始方法被称为,在其中你对Mockito代理一无所知。因此,只有在运行spyTemp.methodB()

时才会调用“覆盖”方法

这应该有效:

Mockito.doReturn(true).when(spyTemp).methodB(Mockito.any()); 
boolean status = spyTemp.methodB("XYZ");

答案 1 :(得分:6)

你创建了一个间谍并嘲笑了methodB()。那是正确的!但是你在原始对象上调用了methodA()。要获得正确的结果,请在间谍

上调用它
boolean status = spyTemp.methodA("XYZ");

答案 2 :(得分:2)

请注意Mockito文档中的以下内容:

  

Mockito 不会委托对传递的实例进行调用   它实际上创建了它的副本。所以,如果你保持真实的实例和   与之互动,不要期望间谍意识到这些   交互及其对实例状态的影响。推论是   当未取消方法在间谍上调用不在   实例,你不会看到对实例的任何影响。

这是指您的具体情况。您保留对temp的引用,然后调用其methodA。 Mockito根本没有监视那个实例;它在spyTemp进行间谍活动。因此调用正常的methodB

请注意,您应该完全避免使用部分模拟新代码。