OK, I think this is very specific to TestNG configurations, since all of the JUnit examples work 'out of the box'!
Read through this link from the PowerMock GitHub site which describes further detail on how to use TestNG together with PowerMock. Exactly your scenario of verifying calls to mocked static
methods is described there using this example code:
@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();
}
}
Which is then followed by this nugget of information:
For this to work you need to tell TestNG to use the PowerMock object factory
This is done using either TestNG XML config, or in the test's code itself. For completeness I've copied below the options given at the above URL. FWIW I extended PowerMockTestCase
and the verification worked as you expect.
Finally, don't forget to @PrepareForTest
the correct class - i.e. the class containing the static
methods which you want to mock, as @Bax pointed out here.
As a further hint (which you probably already know about, but worth mentioning here anyway) since you aren't using Mockito to mock objects, MockitoAnnotations.initMocks(this)
can be safely deleted.
Once you've got all this working, you might also like to consider whether the use of 'Black Magic' tools like Powermock is actually exposing code smells in your design? Especially since it looks like the classes containing static
methods are under your ownership. This means you could use an alternative design that doesn't use static
s. I highly recommend Michael Feathers' book Working Effectively with Legacy Code, it might just change your whole approach to software design and testing...
Good luck!
Configure TestNG to use the PowerMock object factory
Using suite.xml
In your suite.xml add the following in the suite tag:
object-factory="org.powermock.modules.testng.PowerMockObjectFactory"
e.g.
<suite name="dgf" verbose="10"
object-factory="org.powermock.modules.testng.PowerMockObjectFactory">
<test name="dgf">
<classes>
<class name="com.mycompany.Test1"/>
<class name="com.mycompany.Test2"/>
</classes>
</test>
If you're using Maven you may need to point out the file to Surefire:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>suite.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
Programmatically
Add a method like this to your test class:
@ObjectFactory public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
or to be on the safe side you can also extend from the PowerMockTestCase
:
@PrepareForTest(IdGenerator.class)
public class MyTestClass extends PowerMockTestCase { ... }