How to Mock Final Classes in Unit Tests
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.
- Refactor – Refactoring the code you need to mock (so it can be mocked) can be the best solution. Extracting an interface, making a method not final, etc. are all valid options. However, it is not always practical, the class you need to mock could be within a 3rd party library. Also, rewriting a class to make it easier to test, may expose more to your API than desired. Furthermore, I am not a fan of adding boiler plate wrapping classes, just to support unit testing (if it can be avoided). The less code you need to write, the easier it is to maintain.
- Don’t Mock – Mocking isn’t always necessary, and sometimes it is not the best choice. For example, instead of mocking your persistence tier for testing your services, provide a persistence tier that can be used within unit tests. See Unit Testing Your Persistence Tier Code.
- Powermock – There is already an open-source library out there that provides a way to mock final classes. I had difficultlies getting it configured for the tests I needed. Also, it could not be extended to create the desired tests for GWT (this is something I plan on covering in a future article).
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.
- Get the class loader in place so that any class referenced in the unit test will use by the class loader; allow for our unit-test to be written like any other unit test.
- Alter the byte code of the java class when it is being loaded.
- Make sure that classes that should not be modified, are not modified.
- Java 6 – I’m sure Java 5 and Java 7 would work, provided the versions of JUnit, Mockito, and Javassist also worked with the desired version of Java.
- JUnit 4.10 – Junit has gone over some major tranformations in regards to the test runner. Mockito, Spring, and others frameworks provide test runners for making writing unit tests easier. Here we will write a test runner than will allow us to mock those classes and methods that Mockito and Easymock cannot test. Versions since 4.8.2 should work, and I expect versions since 4.7 will also work. The runner changed between version 4.6 and 4.7, so I believe 4.6 and earlier versions of JUnit will not work.
- Mockito 1.9.0 – I am sure this can be applied to older versions of Mockito and other versions of Easymock. While I have used EasyMock longer, I find Mockito easier to use. Mockito has its own JUnit test runner; it will be incorporated into the test runner described here, since I don’t want to loose it’s functionality. I have also tested against version 1.8.5
- Javassist 3.15 – Bytecode manipulation is the key component to removing the final modifier. I’m sure ASM would also work, but personally, I like Javassist. I did some testing against an older version of 3.4, and it worked fine.
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.
One thought on “How to Mock Final Classes in Unit Tests”
Or, um, just use PowerMock or gMock?
Sorry Neil, I see now that you addressed that. I should not skim quite so lightly. Eagerly awaiting your explanation of why PowerMock was inadequate for your needs.
I’m using gMock on my current project. The mocking code and playback almost writes itself, and static, final, and private mocking are trivial.
The problem gMock has that PowerMock doesn’t is that these special encapsulation-breaking mocking features only work when the method invocation is in Groovy code. All other mocking features but these work equally well in Groovy and Java code. Maybe a Groovy-equivalent of your javassist-based code could be helpful to me after all.
JMockIt does a great job of this. It combines the capablities of Mockito and Powermock into one library and goes further.
With powermock it seems you have to constantly worry about versions of mockito and junit for any upgrade.
Also, currently release doesn’t support JUnit 4.10 (see next release section in —
But my main issue was getting JUnit, Mockito, Powermock, and GWT all working together. I’m sure it was something on my end, but the problem that I was trying to solve here seemed trivial and power mock seemed rather heavy. It only took me 3 classes (and one is trivial) to do this, and now I don’t have to worry about the upgrade path of Powermock with Junit and Mockito.
Part of me didn’t feel like writing this article up, due to other options out there. However, I feel this a good reference for using byte code manipulation with a custom class loader. It also shows how to trick-out junit to make this happen (and gives developers a better understanding of what PowerMock must be doing).
As stated in other comments as well we can use PowerMock which is extension of
mockito. Here is a blog that I have put together on the same topic.. http://www.spinachsoftware.com/blog/?p=19
I Thank you very much for your codes Neil,
but i have a problem using it. I’m using Mockito and I want to mock the call on a static method like this(LicenseManager.getInstance()).
I declared class LicenseManager in the annotation @PreMock, using annotation @RunWith(PreMockJUnit4ClassRunner.class) and i use the following code in my test method:
LicenseManager instance = Mockito.mock(LicenseManager.class);
But, I realize that the body of method getInstance is still executed. Can you help me please.
I’ve searched on google for several days and your method seems to be the best to mock final class. please can some body help me to use it with static method?
Hey, Neal. I just ran across your article. It was educational. I have a long time goal of being able to mock out GWT widgets so they can support unit testing without using the (slow) GWTTestCase. I saw your comment about a future article and didn’t find it.
Do you have any advice on how to attack this problem?
Well, I had a lot of issues mocking out all of the GWT/GXT underlying components so ended up going to PowerMock. I wasn’t happy using PowerMock, due to the slowness of it (.5 seconds / test and if you have 100+ tests it adds up).
However, the new project GwtMockito uses the same approach I was attempting to do (using byte code manipulation), but with an internal person of GWT that knows the nuances of GWT was able to get the mocking all in place.
So, GWTMockito @ https://github.com/google/gwtmockito is your best bet. It has been working out extremely well for me. I plan on having a presentation of this at the next GWT user group in the Twin Cities and then will add a blog post about it.
Hey Neil, really cool your article, but look, when i´m trying to set the mocked object at another instance, it´s giving the error:
java.lang.LinkageError: loader constraints violated when linking ….
Do you know what is the real problem?