Do you really need PowerMock framework ?

Kallol Bairagi
5 min readMay 30, 2021

If you are planning to include PowerMock framework for testing your code or planning to remove/replace with other framework like JMockit, EasyMock etc. this article might be helpful. Even if you are interested in choosing and learning about Junit testing frameworks, feel free to go through the article if you have time.

Framework Decision

Let me start with a general overview of some of the frameworks in layman terms. Any kind of frameworks use majorly two kinds of underlying techniques to perform mocking : we can either make mocks by making proxies (Proxy based) or we can perform bytecode manipulation (BM).

Under the hood, all the popular mock frameworks use either of the following libraries : Cglib, ByteBuddy or Javassist. It is important to note that BM is POSSIBLE by all the above mentioned libraries. But, how the framework uses these libraries is the catch.

Java Bytecode generation

The general notion I realized is that using proxy based mock helps in maintaining clean code. Using BM based mock might be helpful if you have a deep and insightful knowledge and if you really know the stuff :P The biggest challenge that I faced is that BM can be misused in a lot of ways which can make it really difficult to maintain clean code in the long run, I am really referring from an enterprise code point of view, where it can get really messy inside the huge ocean of code base.

Mockito framework

This is the most if not, one of the most popular testing framework used all over the world. This framework is proxy based framework. It is simple and really easy to learn and use, which might be the primary reason why it is so extensively used :P Under the hood Mockito earlier used to depend in Cglib library for mocking objects. Mockito has now shifted to using ByteBuddy as their underlying library for mocking objects.

It is mock/stub framework, in simple words, it can mock logic (business logic) present in a object which makes it easier for developers to use it to mock during unit testing. The learning curve is not very steep as it uses simple syntax. For example, if you want to return your own value for a method,

when(mockClass.methodToMock()).thenReturn(mockValue);

or if you want to verify whether any function is getting invoked (2 times) or not,

verify(mockService, times(2)).targetMethodForInvocation();

You get the idea, right ?

The role that the underlying library (ByteBuddy) plays in instantiating the proxy object which can use the same interface or can even extend the same class as the real object. If you are interested in learning more about ByteBuddy, refer link.

A popular limitation of Mockito is often mentioned is that it cannot mock final classes, private methods and static methods. Personally I don't see this as a huge limitation, rather I feel that this helps in maintaining clean code in a standard and uniform way. It is not a good practice to mock static and private methods just for the sake for testing as it defeats the whole purpose of having them in the first place.

Mockito Inline is a new extension of this framework which actually solved the issue of mocking static methods. Using this dependency, it gives the developer more flexibility in terms of mocking. Check out the documentation (link)if you are interested in using it. It is kind of a superset of Mockito as it offers all the features that Mockito used to offer and additionally a lot of improvements as well. Works like a charm !

PowerMock framework

PowerMock has gained popularity due to its ability to handle the limitations Mockito has. It acts as an extension of Mockito and using this framework gives a sweet flexibility to mock anything we want.

Under the hood, PowerMock uses Javassist as its mocking library. It works by actually changing the bytecode in order to mock the private methods, static methods, final methods, constructors etc. by using custom class loader and intercepting the calls to private, static and final methods and classes within the compiled bytecode. This is exactly what we mean by BM is simple terms.

Best visual representation I could find for PowerMock

For the class loader to detect the targeted classes, in Java we usually use the annotation @PrepareForTest() above the test classes,

@PrepareForTest(targetClass.class)

which means we are giving instruction to prepare a particular class for BM which usually consists of static methods or private methods, etc. As a result, the developer can conveniently mocks whatever is required.

Conclusion

It completely depends on use cases on how we want to tackle these kinds of decision. The code base can be legacy or may be newly written, but it always helps to have a better understanding in what is best suited for you. Interestingly, if you visit the PowerMock official website (link), it is clearly written,

Please note that PowerMock is mainly intended for people with expert knowledge in unit testing. Putting it in the hands of junior developers may cause more harm than good.

Personally, I try to use PowerMock as less possible and go with Mockito framework as neither I have expert knowledge in unit testing nor I would want to cause unnecessary bugs. I felt that it is better to refactor some of the code if needed rather to make use of PowerMock as it seems a better practice in the long run and tbh an easier way to maintain clean code.

I hope this read was helpful and remember it always depends on your specific use case.

--

--