#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.
##Background##
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.
##Software Versions##
- Couchbase-lite 1.0.3.1
- Robolectric 2.4
- Dagger 1.2.2
- Mockito 1.10.19
- Android Studio 1.1 Beta 3
##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.java
is a simple Android action bar activity that extends aBaseActivity
and requires aPersistanceManager
to be injected at runtime so it can talk to the database. -
PersisitanceManager.java
is a class that acts as a DAO object toMyActivity
, managing the persistence of 'Map' objects. It offers only INSERT and GET operations in this sample and requires aPersistanceAdapter
implementation to be injected into it. -
PersistanceAdapter.java
is an interface that defines INSERT and GET operations onMap
objects. This interface is required later when mocking & testing. -
CouchbasePersistanceAdapter.java
is a concrete implementation of thePersistanceAdapter
interface. It utilises Couchbase and depends on a couchbaseDatabase
object which must be constructed by Dagger and injected into it. -
The injectable objects that require non-trivial instantiation (like the Couchbase
Database
object for example) are defined by@Provides
methods in a Dagger@Module
in theMyActivityModule
class.
At runtime, Dagger, MyActivity
, 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.
In the app-test
gradle project you'll see the following...
-
MyTestActivity.java
extends the MyActivity class and@Overrides
thegetModules()
method. This method constructs and returns aTestMyActivityModule
instance.TestMyActivityModule
is an inner class which defines an alternative (overriding) Dagger@Module
that can also provide aPersistanceManager
for injection into theMyTestActivity
when testing. This module@Provides
a fake, programmablePersistenceManager
mock, not a real persistance manager as is expected under normal conditions. -
MyActivityRobolectricTest.java
is a standard Robolectric test, but it's Robolectric controller builds a newMyTestActivity
. The methodtestClickingSaveButtonSavesMapAndDisplaysId()
tests that clicking the Save button has the required affect by pre-programming thePersistenceManager
mock 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.
##Acknowledgements##
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:-
You can connect with Ben via his Blog, Website, Twitter or LinkedIn.