Mocking has become a key component to writing effective unit-tests. It is a very useful strategy to write focused tests. Mocking frameworks make it easy to write test, but they have their limitations. Both Mockito and EasyMock cannot mock classes (or methods) that are final. This article will show you how to mock such classes while continuing to use your favorite mocking framework (Mockito for the sake of this article).
In a future article, I will extend this strategy to writing unit tests for Google Web Toolkit (GWT) without the need of the GWTTestCase.
Provide a framework that can mock final classes, while using an existing mocking framework. For this, I have implemented PreMock.
Alter the class, with byte code manipulation, as it is being loaded by a custom class loader. During loading of the class remove the final modifier. When the class is loaded to Mockito it will be a non-final class.
This solution can be found on github as an Eclipse Project, see PreMock. Only 3 classes are needed for PreMock, and they are:
This annotation will be used within the JUnit test to determine which classes can be pre-mocked. This will insure we do not alter a class unexpectedly; only the unit test and classes listed here are loaded by the custom class loader.
Using javassist, this classloader will do byte-code manipulation to remove the annoying final modifier. While the use of javassist here is very light, when I expand on PreMock for GWT testing, javassist will be utilized more. This class-loader will pass all classes to the parent class loader, except for the unit test and the classes annotated in @PreMock.
JUnit does not provide a way to change the class loader, so this ParentRunner does the trick. It reloads the unit test with our custom class loader, and then swaps it in. Once JUnit uses the custom class loader for our test class, we are all set. Please read the comments in the code to understand how this swap takes place. Also, the code provided in the Mockito Test Runner is included, since you can only have one Parent Runner. Mockito’s Runner is what allows the @Mock and @InjectMocks to work.
Here is a unit test that successfully tests a final class with a final method. To see it fail due a final class, simply replace PreMock in the @RunsWith with Mockito’s.
I hope that this can make it easier for you to write unit tests. The easier they are to write, the more likely developers will write them.
The entire source of this blog is accessible from Github at https://github.com/nbuesing/opiblog-premock and is a complete Eclipse project.
In a future article I will extend what I started here to write unit-test for GWT that does not need the GWTTestCase.