DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Testing, Tools, and Frameworks
  4. Android: Unit Testing Apps with Couchbase, Robolectric and Dagger

Android: Unit Testing Apps with Couchbase, Robolectric and Dagger

Ben Wilcock user avatar by
Ben Wilcock
·
Feb. 09, 15 · Interview
Like (0)
Save
Tweet
Share
8.20K Views

Join the DZone community and get the full member experience.

Join For Free

This Android / Gradle project on GitHub 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. With SQL you’re forced to maintain a fixed schema and SQL Lite doesn’t offer any out of the box cloud replication capabilities, unlike most NoSQL databases.

Couchbase Lite for Android is an exciting new embedded NoSQL database, but because its ‘Database’ and ‘Manager’ classes are Final and require native code, it’s not trivial to mock them or integrate them into apps that utilise the popular Robolectrictesting framework.

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 to occur when testing. To achieve this ‘dependency injection’ of mocks, I’ve used Mockito and introduced the Daggerframework into the code.

Software Versions

  1. Couchbase-lite 1.0.3.1
  2. Robolectric 2.4
  3. Dagger 1.2.2
  4. Mockito 1.10.19
  5. Android Studio 1.1 Beta 3 (optional)

About The Sample App

The App I’ve built here is very 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 new document, Couchbase automatically assigns it an ID and it is this ID that is ultimately displayed to the user on the screen after they’ve clicked 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…

1. `MyActivity.java` is a simple Android action bar activity that extends a `BaseActivity` and requires a `PersistanceManager` to be injected at runtime so it can talk to the database.

2. `PersisitanceManager.java` is 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 `PersistanceAdapter` implementation to be injected into it.

3. `PersistanceAdapter.java` is an interface that defines INSERT and GET operations on `Map` objects. This interface is required later when mocking & testing.

4. `CouchbasePersistanceAdapter.java` is a concrete implementation of the `PersistanceAdapter` interface. It utilises Couchbase and depends on a couchbase `Database` object which must be constructed by Dagger and injected into it.

5. 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 the `MyActivityModule` 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

Because it’s also desirable to perform testing without a device or emulator, there’s a set of Robolectric tests for the App’s `MyActivity` class that test the same ‘Save’ feature but without the need for a connected or emulated device and without the need for an embedded Couchbase database.

In the `app-test` gradle project you’ll see the following…

1. `MyTestActivity.java` extends the MyActivity class and `@Overrides` the `getModules()` method. This method constructs and returns a `TestMyActivityModule` instance. `TestMyActivityModule` is an inner class which defines an alternative (overriding) Dagger `@Module` that can also provide a `PersistanceManager` for injection into the `MyTestActivity` when testing. This module `@Provides` a fake, programmable `PersistenceManager` _mock_, not a real persistance manager as is expected under normal conditions.

2. `MyActivityRobolectricTest.java` is 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 `PersistenceManager` mock with behaviours and then verifying that this mock has indeed been called by the Activity as expected.

Running the Sample

To run the tests for yourself just clone or download this repository and then execute the following gradle commands. For completeness, I’ve included some Android Instrumentation Tests as well and 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)

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:- Get the App on Google Play

You can connect with Ben via his Blog, Website, Twitter or LinkedIn.

app unit test Android (robot)

Published at DZone with permission of Ben Wilcock, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • The Data Leakage Nightmare in AI
  • Data Mesh vs. Data Fabric: A Tale of Two New Data Paradigms
  • PostgreSQL: Bulk Loading Data With Node.js and Sequelize
  • DevOps Roadmap for 2022

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: