TestNG + Mockito + PowerMock – verifyStatic()不起作用

我是新的TestNG和一般的unit testing。 我使用的是TestNG 6.9.6和Mockito 1.10.19以及PowerMock 1.6.4。 我想validationMyService类中的myMethod()方法是否在内部使用正确的参数调用静态方法Util.myStaticMethod 。 由于Mockito本身不支持静态方法的validation,因此我使用PowerMock。 我的测试类如下所示:

 public class MyTest { private MyService myService; @Captor ArgumentCaptor argCaptor; @BeforeMethod public void setup() { MockitoAnnotations.initMocks( this ); myService = new MyService(); } @Test @PrepareForTest(MyService.class) public void myTest() { PowerMockito.mockStatic(Util.class); myService.myMethod("arg"); PowerMockito.verifyStatic(10); Util.myStaticMethod(anyString()); } } 

由于myMethod调用静态方法Util.myStaticMethod()一次,因此预计此测试将失败。 但是当我运行测试时,它总是通过,无论我传递给PowerMockito.verifyStatic()值是什么。

另外,如果我在这个类中编写另一个测试方法然后运行测试,我会收到以下错误

 org.mockito.exceptions.misusing.UnfinishedVerificationException: Missing method call for verify(mock) here: -> at mypackage.MyTest.myTest(MyTest.java:21) Example of correct verification: verify(mock).doSomething() Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods. Those methods *cannot* be stubbed/verified. Mocking methods declared on non-public parent classes is not supported. at mypackage.MyTest.myTest.setup(MyTest.java:10) Results : Failed tests: MyTest.setup:10 UnfinishedVerification Missing method call for ver... Tests run: 3, Failures: 1, Errors: 0, Skipped: 1 

它在verifyStatic()方法失败,这使我认为verifyStatic()方法需要更多我不提供的东西。 此外,它表示测试总数为3,而在这种情况下,我只有两种测试方法。

任何帮助,将不胜感激。

编辑:正如所建议的,我尝试将MyUtil类放在@PrepareForTest注释中,它仍然会给出相同的错误。

好吧,我认为这是针对TestNG配置非常具体的,因为所有JUnit示例都可以“开箱即用”!

从PowerMock GitHub站点阅读此链接,该站点详细描述了如何将TestNG与PowerMock一起使用。 使用此示例代码在那里描述了validation对模拟static方法的调用的确切方案:

 @PrepareForTest(IdGenerator.class) public class MyTestClass { @Test public void demoStaticMethodMocking() throws Exception { mockStatic(IdGenerator.class); when(IdGenerator.generateNewId()).thenReturn(2L); new ClassUnderTest().methodToTest(); // Optionally verify that the static method was actually called verifyStatic(); IdGenerator.generateNewId(); } } 

然后是这一小块信息:

为此,您需要告诉TestNG使用PowerMock对象工厂

这是使用TestNG XML配置或测试代码本身完成的。 为了完整起见,我复制了上面URL中给出的选项。 FWIW我扩展了PowerMockTestCase ,validation按预期工作。

最后,不要忘记@PrepareForTest正确的类 – 即包含要模拟的static方法的类,如@Bax在此处指出的那样。

作为进一步的提示(你可能已经知道了,但在这里值得一提)因为你没有使用Mockito来模拟对象, MockitoAnnotations.initMocks(this)可以安全地删除MockitoAnnotations.initMocks(this)

一旦你完成了所有这些工作,你可能还想考虑使用像Powermock这样的’Black Magic’工具是否真的暴露了设计中的代码味道 ? 特别是因为看起来包含static方法的类属于您的所有权。 这意味着您可以使用不使用static s的替代设计。 我强烈推荐Michael Feathers的书“ Working Effectively with Legacy Code” ,它可能只是改变了你对软件设计和测试的整个方法……

祝你好运!

配置TestNG以使用PowerMock对象工厂

使用suite.xml

在您的suite.xml中,在套件标记中添加以下内容: object-factory="org.powermock.modules.testng.PowerMockObjectFactory" eg eg

        

如果你正在使用Maven,你可能需要将文件指向Surefire:

  org.apache.maven.plugins maven-surefire-plugin   suite.xml    

编程

将这样的方法添加到您的测试类:

 @ObjectFactory public IObjectFactory getObjectFactory() { return new org.powermock.modules.testng.PowerMockObjectFactory(); } 

或者为了安全起见,您还可以从PowerMockTestCase扩展:

 @PrepareForTest(IdGenerator.class) public class MyTestClass extends PowerMockTestCase { ... } 

由于此页面在搜索结果中排名很高,我只想在Stephen撰写的有用文档中添加更多内容。 在最初遇到一些问题后,我刚刚成功地将JUnit测试用例迁移到了TestNG。 我发现你既可以执行suite.xml mods,也可以“以编程方式”执行,但是没有必要同时执行这两项操作。

为了以编程方式进行, @ObjectFactory方法对我没有用,但@ObjectFactory PowerMockTestCase 。 这是我的示例代码:

 import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.testng.PowerMockTestCase; import org.testng.annotations.Test; @PrepareForTest(Pokeball.class) public class PokeballTestTestNG extends PowerMockTestCase { // Did not work for me // @ObjectFactory // public IObjectFactory getObjectFactory() { // return new org.powermock.modules.testng.PowerMockObjectFactory(); // } @Test public void test1() throws Exception { PowerMockito.spy(Pokeball.class); Pokeball.getNetworkMessage(); Pokeball.getNetworkMessageLang(42); Pokeball.getNetworkMessageLang(42); PowerMockito.verifyStatic(); //verify one time invocation (default), passes // PowerMockito.verifyStatic(Mockito.times(11)); //fails Pokeball.getNetworkMessage(); //need to call the method per PowerMock operation - actual test is done here - Exception thrown here upon failure PowerMockito.verifyStatic(Mockito.times(2)); Pokeball.getNetworkMessageLang(42); } }