如何使用Mockitovalidation重载方法的调用次数?

我如何检查bar(Alpha, Baz)使用Mockito调用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( ,  ); 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() :在FooFooTest (在第12行) )。

我需要做些什么来使测试做我真正想要的:当我调用bar(Alpha, baz)时确保调用bar(Xray, Baz)同时拦截对bar(Xray, Baz)的调用bar(Xray, Baz) )?

使用eq() Matcher( when(stub.bar(eq(Xray.class), any(Baz.class))... )导致编译错误时, Cannot resolve method 'bar(Class, 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) eq(xray)而不是any(Xray.class)就可以了 – 但我并不真正感兴趣的是将 (特定的)Xray对象作为参数传递给bar() ,只要它是任何 Xray对象……

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

你不需要这样做。

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

您无需测试是否调用了正确的方法,您需要测试行为是否正确 。 那是什么意思?

  1. 你想检查是否返回了"Xray"

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

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

最重要的是:你有你的系统测试,在这种情况下是Foo 。 那堂课应该是真正的class级你的模拟和存根应该是与Foo交互的其他对象 ; validation交互是否正确

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