Mockito的verify方法无法检测到方法调用

5

我正在尝试验证我模拟的对象上是否调用了一个方法:

public class MyClass{
    public String someMethod(int arg){
        otherMethod();
        return "";
    }

    public void otherMethod(){ }
}    

public void testSomething(){
    MyClass myClass = Mockito.mock(MyClass.class);

    Mockito.when(myClass.someMethod(0)).thenReturn("test");

    assertEquals("test", myClass.someMethod(0));

    Mockito.verify(myClass).otherMethod(); // This would fail
}

这并不是我的确切代码,但它模拟了我想要做的事情。当尝试验证是否调用了otherMethod()时,代码将会失败。这正确吗? 我对verify方法的理解是,它应该检测到存根方法(someMethod)中调用的任何方法。

希望我的问题和代码清晰易懂。

1个回答

4
不,Mockito模拟对象将在所有调用上返回null,除非你使用例如thenReturn()等重写它。
你需要的是一个@Spy,例如:
MyClass mc = new MyClass();
MyClass mySpy = Mockito.spy( mc );
...
mySpy.someMethod( 0 );
Mockito.verify( mySpy ).otherMethod();   // This should work, unless you .thenReturn() someMethod!

如果您的问题是someMethod()包含您不想执行而是模拟的代码,则应该注入一个模拟对象而不是模拟方法调用本身,例如:

OtherClass otherClass; // whose methods all throw exceptions in test environment.

public String someMethod(int arg){
    otherClass.methodWeWantMocked();
    otherMethod();
    return "";
}

因此。
MyClass mc = new MyClass();
OtherClass oc = Mockito.mock( OtherClass.class );
mc.setOtherClass( oc );
Mockito.when( oc.methodWeWantMocked() ).thenReturn( "dummy" );

我希望这有意义,能对您有所帮助。
祝好,

谢谢您的回复,但是如果我想在 someMethod 上使用 .thenReturn() 并验证是否调用了 otherMethod,该怎么办呢?此外,当模拟一个类时,这样做不会使 verify 无效吗? - Ryan
2
@Ryan:模拟对象意味着:我不关心你在现实中做什么。相反,按照我的要求去做。因此,如果使用0作为参数调用,则someMethod()的实现将被替换为return“test”;。通常情况下,您会模拟一个依赖项,即被测试类使用的对象,而不是模拟被测试类本身。然后,您可以验证被测试类是否已调用该依赖项。 - JB Nizet
1
间谍和模拟是两个不同的概念,你首先应该明白它们的区别!它们在单元测试中的行为和使用方式也不同。如果问题是你不想调用 someMethod() 中的代码,那么你应该模拟那段代码,而不是模拟 someMethod() 的调用。 - Anders R. Bystrup
@JBNizet说得比我更好。 - Anders R. Bystrup
谢谢大家,我想我需要再多读一些来理解这些概念。 - Ryan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接