35

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?

Ollie C
  • 28,313
  • 34
  • 134
  • 217
pixel
  • 24,905
  • 36
  • 149
  • 251

7 Answers7

38

(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.

ZoFreX
  • 8,812
  • 5
  • 31
  • 51
mxk
  • 43,056
  • 28
  • 105
  • 132
  • 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) – pixel Aug 08 '10 at 18:32
  • 1
    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. – mxk Aug 09 '10 at 10:02
  • I've updated the last paragraph to clarify our approach to this. – mxk Aug 09 '10 at 10:05
  • 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. http://pivotal.github.com/robolectric/ – mxk Nov 23 '10 at 10:49
  • But using Robolectric stops you using PowerMock to mock static methods :-( – Blundell Oct 22 '11 at 00:18
  • Using PowerMock `@Rule`, I believe you can use both, since this allows you to still `@RunWith(RobolectricTestRunner.class)`. See http://blog.jayway.com/2010/12/28/using-powermock-with-spring-integration-testing/ – mxk Oct 22 '11 at 10:14
  • 1
    Apparently with the 1.9.5 release of Mockito, you can use it with dexmaker to work on Android. See http://code.google.com/p/mockito/wiki/ReleaseNotes – ThomasW Jun 05 '12 at 06:55
  • Yes, I've been following the issue report for a while. For reference, here's the original report for it: http://code.google.com/p/mockito/issues/detail?id=308 Haven't gotten around to use it though. – mxk Jun 05 '12 at 07:50
7

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.

om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
Paul Butcher
  • 10,722
  • 3
  • 40
  • 44
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.

Community
  • 1
  • 1
John Lehmann
  • 7,975
  • 4
  • 58
  • 71
1

Lmock is working on Android : github.com/vmware/lmock

Yann
  • 3,841
  • 1
  • 22
  • 14
1

Android Mock is written on top of EasyMock 2.4 which is well-known mock framework for Java

DixonD
  • 6,557
  • 5
  • 31
  • 52
  • Do you have any experience using it? What are pros and cons of using it? – pixel Aug 05 '10 at 06:48
  • 1
    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. – mxk Aug 05 '10 at 07:30
  • a con being it's based on easymock – Steven Oct 03 '11 at 23:16
1

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.

rony l
  • 5,798
  • 5
  • 35
  • 56
0

I have just tried Android-Mock. It works very well so far. It Resolved my issue (either use AndroidTestCase without EasyMock, or use EasyMock but no context allowed)

Bryan Fok
  • 3,277
  • 2
  • 31
  • 59