#Android: Unit Testing Apps with Couchbase, Robolectric and Dagger#
This Android / Gradle project integrates Couchbase, Robolectric and Dagger so that unit testing can occur without the need for a connected device or emulator.
I need a database for my TripComputer app so that users can keep a log of their Journeys. I could use SQL Lite, but I prefer not to use SQL if possible because you're forced to maintain a fixed schema and because SQL Lite doesn't have any out of the box data replication capabilities.
Couchbase Lite for Android is a great alternative to SQL Lite, but because Couchbase's Database manager is Final and requires native code, it's not easy mock or to integrate with Robolectric (the popular Android simulation API).
Therefore, in order to support off-device Java VM based testing with Robolectric it is necessary to write custom interfaces and use a dependency injection framework that will allow the injection of mock objects when testing. To achieve this 'dependency injection', I've introduced the Dagger framework into the code.
##About The Sample App##
The App here is super simple. When the user clicks the Save button on the screen, in the background a new document (technically a
java.util.Map) is created and saved to the embedded Couchbase NoSQL database. While saving the document, Couchbase automatically assigns it an ID and it is this ID that is displayed to the user on the screen after they click the Save button. The document id's in Couchbase take the form of GUID's.
###The App Code###
Roughly speaking, in the
app codebase you'll see the following...
MyActivity.javais a simple Android action bar activity that extends a
BaseActivityand requires a
PersistanceManagerto be injected at runtime so it can talk to the database.
PersisitanceManager.javais a class that acts as a DAO object to
MyActivity, managing the persistence of 'Map' objects. It offers only INSERT and GET operations in this sample and requires a
PersistanceAdapterimplementation to be injected into it.
PersistanceAdapter.javais an interface that defines INSERT and GET operations on
Mapobjects. This interface is required later when mocking & testing.
CouchbasePersistanceAdapter.javais a concrete implementation of the
PersistanceAdapterinterface. It utilises Couchbase and depends on a couchbase
Databaseobject which must be constructed by Dagger and injected into it.
The injectable objects that require non-trivial instantiation (like the Couchbase
Databaseobject for example) are defined by
@Providesmethods in a Dagger
At runtime, Dagger,
BaseActivity and the
App application classes take care of constructing an
ObjectGraph for the application and inserting the required dependencies so that all the various
@Inject requirements can be met. The "Instrumentation (integration) Tests" in the Android App gradle project test that this integration and dependency injection is working as expected.
###The Robolectric Tests###
However, because its often desirable to perform testing without a device or emulator, there is also a set of Robolectric tests for the App.
app-test gradle project you'll see the following...
MyTestActivity.javaextends the MyActivity class and
getModules()method. This method constructs and returns a
TestMyActivityModuleis an inner class which defines an alternative (overriding) Dagger
@Modulethat can also provide a
PersistanceManagerfor injection into the
MyTestActivitywhen testing. This module
@Providesa fake, programmable
PersistenceManagermock, not a real persistance manager as is expected under normal conditions.
MyActivityRobolectricTest.javais a standard Robolectric test, but it's Robolectric controller builds a new
MyTestActivity. The method
testClickingSaveButtonSavesMapAndDisplaysId()tests that clicking the Save button has the required affect by pre-programming the
PersistenceManagermock with behaviours and then verifying that this mock has indeed been called by the Activity as expected.
##Running the Sample##
To run the sample just clone or download this repository and then execute the following commands. For completeness, i've included some Instrumentation Tests also (you can run them with
gradlew connectedCheck assuming an emulator or device is present).
gradlew clean gradlew assemble gradlew check gradlew connectedCheck (this is optional and assumes a device is present)
##Notes## Dagger is about to be replaced by Dagger 2.0, but this timeline for release is unclear and has slipped several times last year already, hence the use of Dagger 1.2.2.
Many thanks to Andy Dennie for his Dagger examples on GitHub. These were really helpful to this Dagger noob when trying to understand how to integrate Dagger with Android.
##About the Author##
Ben Wilcock is the developer of TripComputer , the only distance tracking app for Android with a battery-saving LOW POWER mode. It’s perfect for cyclists, runners, walkers, hand-gliders, pilots and drivers. It’s free! Download it from the Google Play Store now:-