Android testing with JUnit, Mockito and Robolectric
Posted Jan 23, 2014 | 4 min. (713 words)We’ve been busy with our crash reporting for Android and thought we’d share some ways we do Android testing. Raygun is all about helping improve software quality, but is useful later in the pipeline, usually in production. To assist in creating great software, you’ll want to be testing your Android code base well before deployment.
Here are some of the tools I’ve used that I’ve found great for Android testing. If I’ve missed any you find useful then drop a comment!
Maven builds + JUnit
JUnit’s the perennial favorite for unit testing, and it’ll come as no surprise to many of you to see it appearing first. The concept originated from Smalltalk with SUnit, and following the enormous popularity of Java in the last 1.5 decades, almost every language of note now sports an xUnit library. With that in mind not much needs to be said about it, apart from a bit of boilerplate to show how it can be wired into an Android Maven workflow to run tests automatically on build.
The first dependency grabs the Android SDK, the second is the Maven plugin that builds your Android module, while the third is JUnit.
pom.xml
<project>
...
<dependencies>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>android</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>
...
</project>
Mockito
Mockito is a powerful mocking framework that allows you to use stubbed-out classes and provide sane values for their properties and methods. Adding it just takes one more dependency in your pom.xml:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
It’s got a nifty semantic syntax that lets you specify the result of methods. Here we can mock the abstract android.context.Context, which would otherwise throw a RuntimeException(“Stub!”) message and be unavailable from outside an Android Activity:
Context context;
@Before
public void SetUp()
{
context = mock(Context.class);
}
@Test
public void test_deleteFile()
{
when(context.deleteFile("foo")).thenReturn(true);
assertTrue(myMethodThatDeletesAFile());
}
This allows you to ensure that a certain action is completed by your app, without actually performing that action where it wouldn’t make sense (as it’s being run headlessly, not in an emulator). It’s also really valuable when a library (e.g many things in the Android SDK) will crash your tests due to RuntimeExceptions.
Robolectric
This library also allows you to mock the Android SDK by removing the stubs that throw RuntimeExceptions. It essentially gives you the ability to run black-box tests by programmatically manipulating your Activity as if you manually fired it up in an emulator. This is done by getting elements with findViewById, then asserting their effects on other UI elements. This is in contrast to using pure Mockito, which often ends up with tests that are the reverse of the logic you are attempting to test.
Robolectric works by emulating the native calls the SDK would make on Dalvik, but on the JVM, so it can run much, much faster. This makes full unit testing and TDD possible.
To use the library, add this dependency to your pom.xml:
<dependency>
<groupId>org.robolectric</groupId>
<artifactId>robolectric</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
And this annotation above your test Activity:
@RunWith(RobolectricTestRunner.class)
Creating a mocked Activity to work with is as easy as this:
Activity activity = Robolectric.buildActivity(MyActivity.class).create().get();
You can then validate the result of button clicks, API calls, and more.
Unit testing’s a good start
…and will result in more reliable code now and in the future. It’s not the full story, however – integration testing is important, and the process must be continued as your app reaches release and enters its maintainance phase. An important concern is error visibilty on the thousands of possible devices your app will run on – unit testing can guarantee that the app’s state is sane, but can’t cover the huge variability in hardware.
That’s where Raygun comes in – it can show you what errors are occurring for every version you’ve released, how many users are being affected, what devices they’re using – not to mention the full stack trace for every exception. All this data is available but often it’s lost immediately, and perhaps even a customer with it (few even bother to report bugs they’ve come across).
If you’re sorted on the unit testing front and want visibility on your app’s health, start your free 14-day trial of Raygun now – no credit card needed. Thanks for reading!