1

鉴于我的 MCVE 类,我如何检查是否使用 Mockito 调用 - 无需实际调用bar(Alpha, Baz)后者:bar(Xray, Baz)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)

我想这是因为any(Class.class)匹配任何东西,并且不进行类型检查......所以,从 Mockito 的角度来看,我真的打bar()了两次电话:inFoo和 in FooTest(第 12 行)。

我必须做些什么才能使测试做我真正想要的:确保bar(Xray, Baz)在我调用时被调用bar(Alpha, baz)(同时拦截对 的调用bar(Xray, Baz))?

使用eq()Matcher ( when(stub.bar(eq(Xray.class), any(Baz.class))...) 会导致编译错误,Cannot resolve method 'bar(Class<Xray>, Baz)'- 但是,我可能不应该那样使用它(eq(xray)可能会更喜欢它)......

此外,在相关说明中,如果我尝试对 进行重载,则会bar(Alpha, Baz) private收到 的编译错误FooTest,说明:

错误:(10, 12) java: bar(Xray,Baz) 在 Foo 中具有私有访问权限

有没有办法使用 PowerMockito 来解决这个问题?如何?(显然,我只想计算调用bar(Xray, Baz)- 计算对所有重载的所有调用bar()是不可能的......)

只需在测试的第 10 行和第 14 行使用eq(xray)而不是使用any(Xray.class)就可以了 - 但我并不真正感兴趣的是什么(特定)Xray 对象作为参数传递给bar(),只要它是任何 Xray对象......

更新:我已经为讨论的“PowerMockito 和方法”部分发布了一个单独private的问题,并弄清楚了如何使这项工作适用于public方法;参看。我的评论如下

4

1 回答 1

3

你不需要这样做。

这让你发疯的原因是你没有按照预期的方式使用 Mockito。可以这样使用,但不应该这样。

您不需要测试是否调用了正确的方法,您需要测试您的类的行为是否正确。这意味着什么?

  1. 您要检查是否"Xray"已退回。

    String result = foo.bar(alpha, baz);
    assertEquals("Xray", result);
    
  2. 你想检查那个Alpha.get被调用的。如果有的话,这意味着Alpha应该是存根,而不是Foo.

    Alpha alpha = spy(new Alpha());
    String result = foo.bar(alpha, baz);
    verify(alpha).get();
    

底线是:在这种情况下,您有您的系统被测Foo。那个班级应该是真正的班级您的模拟和存根应该是与之交互的其他对象Foo;验证交互是否正确

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

于 2015-08-25T14:31:24.280 回答