我正在使用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的定义。然而,情况似乎并非如此。
有人可以解释我哪里出错吗?
答案 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
。
请注意,您应该完全避免使用部分模拟新代码。