Fixing Common PowerMock Problems

PowerMock is a great tool for static / final mocking, but exhibits odd behavior in some cases. This post covers three of the most common PowerMock problems I’ve encountered.

PowerMock
A test class annotated for PowerMock.

Intro to PowerMock

PowerMock is useful in cases that a tool like Mockito can’t handle — namely mocking final classes and static methods.

There are many reasons why you shouldn’t aspire to mocking static methods, but sometimes it can’t be avoided.

To mock with PowerMock, you have to use the @PrepareForTest annotation, which sets up the class being mocked (it dynamically loads another class to wrap it). You can also use the @PowerMockIgnore annotation to specify classes that should be ignored when the mock occurs.

This post includes some examples of PowerMock in action, which you can find here.

Common PowerMock Problems

Mocking Core Java Classes

By default, a lot of Java system classes are ignored by PowerMock, meaning you can’t mock them the way you would any other class.

To show what happens when you do this type of mock, consider this example using the java.net.NetworkInterface class.

I have one other class in the test (creatively called OtherClass), whose call takes a NetworkInterface object, calls it’s isUp() method, and returns the result:

My first test shows that the mock is created successfully by calling isUp() method from within the test method (code):

This test passes, but if you try and use this same mock in a different class, it won’t work (code):

The NetworkInterface class, as a standard Java class, is ignored by PowerMock, so the call to isUp() doesn’t result in the expected mocked call.

To fix this, you need to @PrepareForTest the class calling NetworkInterface#isUp(), OtherClassrather than the class being mocked (code):

The test now passes, and the mock is successfully executed.

@PrepareForTest disables code coverage tools for the prepared class, which is hard to fix. The only way around this problem is to not mock Java system classes, which you could do by wrapping system class and all calls to it.

OutOfMemory PermGen Errors

PowerMock seems prone to the ‘java.lang.OutOfMemoryError: PermGen space' error, because it does so much dynamic class loading. There are some useful blog posts on this (1), but they tend to be a little too optimistic about this problem being completely fixed.

There are a number of ways to fix a PermGen error:

  1. Increase your PermGen size. Since it’s only an issue with tests, this may not be such a big deal (2)
  2. Pool mocks to limit the volume of classloading (3)
  3. Avoid using mocks entirely, instead using anonymous test classes (3)

Test Class Doesn’t Run: java.lang.VerifyError

I had this issue using PowerMock in unit test classes that had a superclass.

It happens because Oracle made Java’s bytecode checking stricter in Java 7, so it can be fixed with by stopping this checking using -noverify as a JVM argument.

If you’re not the kind of person to take that as an acceptable answer (good call), I fixed this issue by updating my version of the JDK (in my case from 7_72 to 7_79). It’s not clear that one version of the JDK definitively fixed this problem (people seem to report it as being fixed before 7_72, for example), but it’s worth updating the JDK and your version of PowerMock before resorting to -noverify.

Other Resources