How-to Dagger 2 with Android: Part 2

John Tucker
ProAndroidDev
Published in
3 min readNov 29, 2017

By introducing testing with Espresso, we see another value of dependency injection with Dagger 2.

note: If you are wondering why all the images of black holes in this series, it is because I am finding myself being sucked deeper and deeper into the topic of dependency injection.

This article is part of a series on dependency injection with Dagger 2; starting with How-to Dagger 2 with Android: Part 1.

In the last article, we ended up creating an example application with:

  • An interface, MyExample, with a getDate method.
  • A concrete implementation of this interface, MyExampleImpl, that stores and returns the current date (as a long).
  • An activity, MainActivity, that has a dependency on this interface (shows the date formatted on the screen).
  • Using Dagger 2, we injected the concrete implementation as a singleton into the activity.

While the example was simple, it does not illuminate the benefits of dependency injection; we only have one concrete implementation of the interface. By adding testing to the mix, however, this example demonstrates the benefit of dependency injection.

For example, say we wanted to have an automated test of MainActivity to ensure that it shows the date in particular format. As the MyExampleImpl implementation provides the current date, it would be (sort of) difficult to write a test that validates the formatted date. It would be so much easier if we could replace MyExampleImpl with a mock implementation that provides a known date and thus easily validate against a known formatted result, e.g, the date of 0 should show as Wed Dec 31 19:00:00 EST 1969.

Dagger Espresso

In this example, we refactor the previous example to support testing the date format using the Espresso testing framework. This article assumes that you already have a basic understanding of Espresso and have it installed.

note: The good news is that if you are using the latest version of Android Studio (3.0.1 as of this writing), Espresso comes pre-installed.

The complete solution is available:

Looking at MainActivity.java, we can trace the source of the implementation of the MyExample interface back to MyApplication.

Likewise, we can see in MyApplication.java that the component (including the module and thus MyExampleImpl) is built when the application is created.

The general idea of this solution is that we will write a test that first replaces the component in MyApplication with a mock one and then run the test on MainActivity. To facilitate this, we add a setter to MyApplication.java.

We then need to create a mock component, mock module, and finally a mock implementation of the MyExample interface. In many articles that I read on this topic, the author would collect all these mocks in the test folder. Being a fan of organizing code by feature not function, I rather put them along side the code that they are mocking (but in a mocks package).

With the these in place, we can now write the test, MainActivityTest.java, with MyExampleImplMock being used.

Next Steps

So far our components were stand-alone Singletons that lived as long as the application did, we explore some new concepts to break free of these constraints in How-to Dagger 2 with Android: Part 3.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Written by John Tucker

Broad infrastructure, development, and soft-skill background

Responses (1)

What are your thoughts?