Mocking library/framework that works best in Android?

15,618

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.

A comparison to Mockito.

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.

Share:
15,618
pixel
Author by

pixel

Updated on July 16, 2022

Comments

  • pixel
    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
    pixel almost 14 years
    Do you have any experience using it? What are pros and cons of using it?
  • Matthias
    Matthias almost 14 years
    We 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
    pixel almost 14 years
    You'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
    Matthias almost 14 years
    We 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
    Matthias almost 14 years
    I've updated the last paragraph to clarify our approach to this.
  • Matthias
    Matthias over 13 years
    By 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
    Steven over 12 years
    a con being it's based on easymock
  • Blundell
    Blundell over 12 years
    But using Robolectric stops you using PowerMock to mock static methods :-(
  • Matthias
    Matthias over 12 years
    Using 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
    ThomasW about 12 years
    Apparently 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
    Matthias about 12 years
    Yes, 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.