Mocking classes in Android with JMock, JMockIt or EasyMock
* I stand corrected. A commenter, Kiran Gunda, says it’s possible to mock f inal methods with JMockIt. I may have set the mock up incorrectly. If I try again, I’ll update this post. Until then, an updated post describes how I used Android test classes to run my code. Matt also pointed out that JMock can mock final methods using JDave’s unfinalizer.
* Updated July 11, 2009 to remove some incorrect information
So that you don’t have to read this whole post, I’ll sumarize what I discovered. If you’re thinking about using a mocking library to mock Android classes, don’t. Android uses interfaces sparsely. That makes a clean API with lots of reusable code, but makes mocking difficult. The real problem, though, is caused by Android’s generous use of final methods. I don’t know of any mocking library that can mock final methods, so you just can’t do it. Instead of writing mocks, look into the android.test and android.test.mock packages.
I developed GreenMileage so that I could learn about the Android OS. Now that I have an understanding of it, I decided to go back and write test cases so that I could continue development using TDD. I started by writing tests for utility classes. That wasn’t a problem. After finishing that, I moved to some simple UI cases. The first was TextViewCallbackListener. I just had to mock TextView.setText(String).
First, I spent hours just trying to get the JMock jars into the project. For some reason, the compiler would not put JMock into the APK. I didn’t get any error message or notification. It just wasn’t there.
I decided to use Android’s test mocks to run my code. Click here to see a simple example.
Usually tests are ran on a desktop vm like a “normal” sun vm. So it seems that JMockIt is usable for Android projects.
Concerning JMockIt and Android, it doesn’t seem possible to use the one with the other, as JMockIt is using instrumentation to accomplish these features and the Android JVM unfortunately doesn’t support Java 5 Instrumentation.
These other comments are correct. JMockit uses java.lang.instrument to hook the bytecode. By analogy to C++, it overwrites the function pointers in the vtable to call your methods instead of the ones defined in the classes being mocked. JMockit ignores static, final, private, and protected modifiers. It ignores throws declarations. All it cares about is that the parameter types match and that the return types match between the original methods and the ones you write to replace the original methods. It can even mock constructors, including the default constructor. I’ve used JMockit extensively, and it works great. Its only real limitation is mocking JRE classes, which isn’t an issue here (and can be done–but requires launching your code in the boot classloader).
You can mock final classes and methods with jMock by using the unfinalizer agent from the JDave project, as described in the jMock documentation: http://www.jmock.org/mocking-classes.html
Hi, I am not sure why Mocking failed using JMockit. But JMockit supports the mocking of final classes and final methods and I am currently using JMockit to mock the final classes/methods in my project.
Thanks, Kiran