Mocking library/framework that works best in Android?
Solution 1
(Update: Mockito has added Android support as of version 1.9.5 and EasyMock has added Android support as of version 3.2 by factoring out those bits that generate code at runtime and making them pluggable, e.g. by using dexmaker instead of cglib.)
Except for android-mock mentioned by DixonD (which is a fairly young, unproven library), there currently is no solution. You can immediately forget anything based on CGLib (Mockito, plain EasyMock), since CGLib relies on byte code generation and won't work on Dalvik (it also relies on the Java Beans package, which is also not part of Android).
For what it's worth, you could use the very few mock classes coming with Android (like MockContext), but they don't verify behavior, they're just stubs. Their default behavior is to throw a runtime error in every method, so you have to subclass them and override the methods you want to mock.
However, you can still use mocking libraries in non-instrumentation tests, i.e. in your standard unit tests executed on the JVM. You can use PowerMock to mock framework methods, it has support for mocking static methods and constructors, making the mocking as powerful as e.g. in Ruby (just more painful to use).
We use JUnit 4 + PowerMock + Mockito and mock out classes like Context and TextUtils in a base class from which we inherit every normal JUnit test. For instrumentation tests, we create custom mock classes and decide using a factory which implementation (mock or not) to instantiate at runtime.
Solution 2
I recently released Borachio, a native Scala mocking framework which works on Android.
Because Borachio is written in Scala, you’ll need to write your tests in Scala. But it can be used to test code written in Java.
There's a description of how to use Borachio on Android on my blog:
http://www.paulbutcher.com/2011/03/mock-objects-on-android-with-borachio-part-1/ http://www.paulbutcher.com/2011/03/mock-objects-on-android-with-borachio-part-2/ http://www.paulbutcher.com/2011/03/mock-objects-on-android-with-borachio-part-3/
UPDATE:
Borachio now is ScalaMock.
Solution 3
Robolectric uses a different approach. Instead of running on the DVM, it "defangs" the Android SDK so that you can run Android tests directly on the JVM with the JUnit4 framework. Tests apparently build and run much faster, and require less mocking.
[A common approach] is to use mock frameworks such as Mockito or Android Mock to mock out the Android SDK. While this is a valid approach, we have found that without Robolectric, the level of mocking needed to test an Android app quickly yields tests that are essentially reverse implementations of the application code.
Robolectric allows a test style that is closer to black box testing, making the tests more effective for refactoring and allowing the tests to focus on the behavior of the application instead of the implementation of Android. You can still use a mocking framework along with Robolectric if you like.
Here's how it works:
[It intercepts] the loading of the Android classes and rewriting the method bodies. Robolectric re-defines Android methods so they return null (or 0, false, etc.), or if provided Robolectric will forward method calls to shadow Android objects giving the Android SDK behavior.
Solution 4
Android Mock is written on top of EasyMock 2.4 which is well-known mock framework for Java
Solution 5
update: looks like easymock 3.2 added an option for plugging-in alternatives for cglib.
I'm using easymock 2.5.2 (note - do not use 3.X). it works - but only for mocking interfaces.
Thus if your library exposes interfaces or if you're willing to wrap our dependencies with interfaces you can use easymock.
Later easymock versions such as easymock 3.x won't work because they use the android-incompatible cglib for bytecode manipulation for both classes and interfaces while 2.x uses it only for mocking classes.
pixel
Updated on July 16, 2022Comments
-
pixel almost 2 years
I'm developing Android application using third party libraries (Twitter4j). I want to be able mock those objects (also objects created by me) in JUnit and functional tests.
Do you have any good experiences using some mocking libraries and you can recommend them?
-
pixel almost 14 yearsDo you have any experience using it? What are pros and cons of using it?
-
Matthias almost 14 yearsWe also found that project a while ago, but it doesn't look very active... I'd rather not rely on a pre-alpha release of something I use to verify my app's behaviour.
-
pixel almost 14 yearsYou've written that you use Mockito to mock Context - how you are doing that contrary to your first paragraph (that it can't be run because it relies on CGLib)
-
Matthias almost 14 yearsWe distinguish between tests running on the JVM and instrumentation (UI unit and story tests) which run on the emulator (i.e. the Dalvik VM). For instance, our API connector has a dependency on a Context, but the unit test for that class is not executed on the emulator, so we can mock out the Context using Mockito and Powermock. Anything that involves running an Activity though has to be run on the emulator, where these libraries won't work.
-
Matthias almost 14 yearsI've updated the last paragraph to clarify our approach to this.
-
Matthias over 13 yearsBy the way, there has been new movement in this area, thanks to the guys from Pivotal: Robolectric uses "shadow classes" to allow testing against Android framework classes on a standard JVM. pivotal.github.com/robolectric
-
Steven over 12 yearsa con being it's based on easymock
-
Blundell over 12 yearsBut using Robolectric stops you using PowerMock to mock static methods :-(
-
Matthias over 12 yearsUsing PowerMock
@Rule
, I believe you can use both, since this allows you to still@RunWith(RobolectricTestRunner.class)
. See blog.jayway.com/2010/12/28/… -
ThomasW about 12 yearsApparently with the 1.9.5 release of Mockito, you can use it with dexmaker to work on Android. See code.google.com/p/mockito/wiki/ReleaseNotes
-
Matthias about 12 yearsYes, I've been following the issue report for a while. For reference, here's the original report for it: code.google.com/p/mockito/issues/detail?id=308 Haven't gotten around to use it though.