One of my biggest frustrations with writing code for Android has been the fact that none of the current Java mocking frameworks work on Android’s Dalvik VM. I tried to address that myself by getting ScalaMock working on Android, but that’s been less successful than I hoped (primarily due to general problems with getting Scala working in the Android environment).
Happily there’s been a major breakthrough recently – Mockito, one of the established Java mocking frameworks now supports Android
In this article, I’ll go through getting an Android application up and running with tests written using Mockito.
This is an Android version of the example in Martin Fowler’s article Mocks Aren’t Stubs. The code is checked into GitHub here. You’ll need to have the Android SDK and ADT Plugin for Eclipse installed to run this code.
We’re going to build a (very) simple ordering system. Orders will succeed if there’s enough inventory in our warehouse and fail if not. Let’s start by creating a very simple little Android application for us to test:
-
Create a new Android project in Eclipse called
WarehouseManager. Select the “Create a Test Project” option. -
The core abstraction is a warehouse, represented by a
Warehouseinterface:package com.example; public interface Warehouse { boolean hasInventory(String product, int quantity); void remove(String product, int quantity); }
-
And here’s a very simple concrete implementation of
Warehouse:package com.example; import java.util.HashMap; public class RealWarehouse implements Warehouse { public RealWarehouse() { products = new HashMap<String, Integer>(); products.put("Talisker", 5); products.put("Lagavulin", 2); } public boolean hasInventory(String product, int quantity) { return inStock(product) >= quantity; } public void remove(String product, int quantity) { products.put(product, inStock(product) - quantity); } private int inStock(String product) { Integer quantity = products.get(product); return quantity == null ? 0 : quantity; } private HashMap<String, Integer> products; }
-
We remove things from the warehouse by placing an
Order:package com.example; public class Order { public Order(String product, int quantity) { this.product = product; this.quantity = quantity; } public void fill(Warehouse warehouse) { if (warehouse.hasInventory(product, quantity)) { warehouse.remove(product, quantity); filled = true; } } public boolean isFilled() { return filled; } private boolean filled = false; private String product; private int quantity; }
-
We’ll need a UI to allow us to make orders, so modify
main.xmlto look like this:<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Product:" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/product" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Quantity:" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/quantity" /> <Button android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="Place order" android:onClick="placeOrder" /> </LinearLayout>
-
And finally, here’s the implementation of
WarehouseManagerActivity:package com.example; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.Toast; public class WarehouseManagerActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); productEditText = (EditText)findViewById(R.id.product); quantityEditText = (EditText)findViewById(R.id.quantity); } public void placeOrder(View view) { String product = productEditText.getText().toString(); int quantity = Integer.parseInt(quantityEditText.getText().toString()); Order order = new Order(product, quantity); order.fill(warehouse); String message = order.isFilled() ? "Success" : "Failure"; Toast toast = Toast.makeText(this, message, Toast.LENGTH_SHORT); toast.show(); } private Warehouse warehouse = new RealWarehouse(); private EditText productEditText; private EditText quantityEditText; }
You should now have a little Android application that can be compiled and installed with ant install. Here’s what it looks like:

So, now that we’ve got something to test, let’s test it:
-
The version of Mockito that supports Android has not yet been released, so you’ll need to get the source and build it for yourself. After building, you should have
mockito-all-1.9.1-SNAPSHOT.jarin thetargetdirectory. -
Create a
libsdirectory underneathWarehouseManagerTestand copymockito-all-1.9.1-SNAPSHOT.jarinto it. Download the latest dexmaker into the same directory. -
Finally, we can write our tests, which create mock instances of the
Warehouseinterface:package com.example.test; import android.test.InstrumentationTestCase; import com.example.*; import static org.mockito.Mockito.*; public class OrderTest extends InstrumentationTestCase { public void testInStock() { Warehouse mockWarehouse = mock(Warehouse.class); when(mockWarehouse.hasInventory("Talisker", 50)).thenReturn(true); Order order = new Order("Talisker", 50); order.fill(mockWarehouse); assertTrue(order.isFilled()); verify(mockWarehouse).remove("Talisker", 50); } public void testOutOfStock() { Warehouse mockWarehouse = mock(Warehouse.class); when(mockWarehouse.hasInventory("Talisker", 50)).thenReturn(false); Order order = new Order("Talisker", 50); order.fill(mockWarehouse); assertFalse(order.isFilled()); } }
-
Run your tests

