同一类中的模拟方法

lea*_*hru 16 java unit-testing mocking mockito

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

 class Temp() {

    public boolean methodA(String param) {

         try {

             if(methodB(param))
                   return true;

             return false;
         } catch (Exception e) {
               e.printStackTrace();
         }
    }
 }
Run Code Online (Sandbox Code Playgroud)

我的测试方法:

 @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);
 }
Run Code Online (Sandbox Code Playgroud)

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

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

Kon*_*bun 14

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

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

这应该工作:

Mockito.doReturn(true).when(spyTemp).methodB(Mockito.any()); 
boolean status = spyTemp.methodB("XYZ");
Run Code Online (Sandbox Code Playgroud)


Cor*_*onA 7

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

boolean status = spyTemp.methodA("XYZ");
Run Code Online (Sandbox Code Playgroud)


spr*_*ter 7

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

Mockito不会将调用委托给传递的真实实例,而是实际创建它的副本。因此,如果您保留真实实例并与之交互,则不要指望被监视的人会知道这些交互及其对真实实例状态的影响。推论是,当在 spy不是在真实实例上调用unstubbed方法时,您将看不到对真实实例的任何影响。

这是特指你的情况。您保留对的引用temp,然后调用它的methodA. Mockito 根本没有监视那个实例;它在监视spyTemp。所以methodB调用法线。

请注意,您应该完全避免对新代码进行部分模拟。