Java 如何使用Mockito验证重载方法的调用次数?

Java 如何使用Mockito验证重载方法的调用次数?,java,mockito,powermock,overloading,powermockito,Java,Mockito,Powermock,Overloading,Powermockito,如何使用Mockito检查bar(Alpha,Baz)是否调用了bar(Xray,Baz),而不实际调用后者,考虑到我的MCVE类Foo: public class Foo { public String bar(Xray xray, Baz baz) { return "Xray"; } public String bar(Zulu zulu, Baz baz) { return "Zulu"; } public St

如何使用Mockito检查
bar(Alpha,Baz)
是否调用了
bar(Xray,Baz)
,而不实际调用后者,考虑到我的MCVE类
Foo

public class Foo {
    public String bar(Xray xray, Baz baz) {
        return "Xray";
    }

    public String bar(Zulu zulu, Baz baz) {
        return "Zulu";
    }

    public String bar(Alpha alpha, Baz baz) {
        if(alpha.get() instanceof Xray) {
            return bar((Xray)alpha.get(), baz);
        } else if(alpha.get() instanceof Zulu) {
            return bar((Zulu)alpha.get(), baz);
        } else {
            return null;
        }
    }
}
目前,我大致有以下Mockito增强JUnit测试:

@Test
public void testBar_callsBarWithXray() {
    Baz baz = new Baz(); //POJOs
    Alpha alpha = new Alpha();
    alpha.set(new Xray());

    Foo foo = new Foo();
    Foo stub = spy(foo); // Spying on Foo, as I want to call the real bar(Alpha, Baz)
    // Preventing bar(Xray, Baz) from being called by providing behavior/stub
    when(stub.bar(any(Xray.class), any(Baz.class))).thenReturn("ok");
    // Calling the real "parent" method
    stub.bar(alpha, baz);
    // Testing if bar(Xray, Baz) was called by bar(Alpha, Baz)
    verify(stub, times(1)).bar(any(Xray.class), any(Baz.class));
}
但它失败了:

org.mockito.exceptions.verification.TooManyActualInvocations:
foo.bar(
    <any>,
    <any> ); 
Wanted 1 time:
-> at FooTest.testBar_callsBarWithXray(FooTest.java:14) 
But was 2 times. Undesired invocation:
-> at FooTest.testBar_callsBarWithXray(FooTest.java:12)
org.mockito.exceptions.verification.ToomanyActualInvestations:
美食酒吧(
对于讨论的“PowerMockito和
private
methods”部分,我们了解了如何为
public
方法实现这一点;请参阅my.

您不需要这样做。 这让你抓狂的原因是你没有按预期的方式使用Mockito。它可以这样使用,但不应该这样

您不需要测试是否调用了正确的方法,您需要测试类的行为是否正确

  • 您要检查是否返回了
    “Xray”

    String result = foo.bar(alpha, baz);
    assertEquals("Xray", result);
    
  • 您想检查是否调用了
    Alpha.get
    。如果有任何问题,这意味着
    Alpha
    应该是存根,而不是
    Foo

    Alpha alpha = spy(new Alpha());
    String result = foo.bar(alpha, baz);
    verify(alpha).get();
    
  • 底线是:您的系统正在测试中,在本例中是
    Foo
    。该类应该是真实类您的mock和stub应该是与
    Foo
    交互的其他对象;验证交互是否正确


    换句话说,你不应该测试
    Foo
    是如何工作的,你应该测试
    Foo
    做了它应该做的事情;结果是正确的。

    我有一个简单的例子,它删去了
    Alpha
    以包含一个通过测试的方法
    get
    set
    。你能包括更多吗我们可以看到的代码,以便我们也可以运行您的确切案例?墨菲定律,我想…我上面的示例实际上也适用于我,现在我尝试了它-尽管我无法发现差异。对此表示抱歉。无论如何,当我设置断点并通过真实事件时,我收到了另一条错误消息:“org.mockito.exceptions.misusing.ErrorTypeOfReturnValue…间谍使用when(spy.foo()).then()语法进行存根。使用doReturn系列方法来存根间谍更安全。有关mockito.spy()方法的详细信息,请参阅javadocs。”果然,
    doReturn(“ok”).when(stub.bar)(any(Xray.class),any(Baz.class))
    成功了。不过,别问我为什么——我不知道……我们目前正在进行重构,正如我们正在编写新代码一样,我不想一直重写测试——因此我尝试测试最小的单元:方法(而不是类)。但我很欣赏你的观点…;-)@克里斯蒂安,但我的答案确实测试了一种方法……它测试
    bar
    是否做了正确的事情。。。