The Startup
Published in

The Startup

Unit Testing With Dagger 2: Brewing a Potion With Fakes, Mocks, and Custom Rules in Android

Photo by Jan Ranft on Unsplash

If you have Dagger in your project but never used it for testing, it’s high time to give it a try. Dagger makes your code so much easier to test. Once the test setup is complete, all you have to do is plug and play with the dependencies. Also, dependency injection is a crucial concept in testing, and you should use it whenever possible.

I highly recommend having hands-on experience in Dagger and Unit testing before going through the article. It’s required to have the fundamental knowledge of Dagger to understand how things work under the hood.

Exploring the Test Application


The sample app has only one screen that searches through Github repo by a keyword. The app fetches the API response through a Data Repository and outputs the result inside a ViewModel. Finally, an Activity watches for LiveDatachanges and sets the output inside a TextView.

Dagger Configuration

The test project has five application-level modules and one module for each Activity.

The functionality of each module:


This module works as an entry point for all of the Activities. Whenever there’s a new Activity in the app, we can add it to the module with a @ContributesAndroidInjector annotation. Inside the annotation, we can pass the modules for the given Activity, e.g., Fragment, ViewModel. It will create a sub-component for the modules and add it as a child to the Activity.


It returns app-specific dependencies created with a @Provides annotation.


It returns app-specific dependencies created with a @Binds annotation.


It returns everything related to the Networking stuff. E.g., Retrofit, OkHttp etc.


AppComponent hosts all modules and facilitates the Dagger dependency tree.


Finally, We have our BaseApplication class to initialize the Dagger process.

Test Goals

For the sake of simplicity, let’s test the DefaultDataRepositoryfrom the data package. It has only one method, getSearchResponse() to search through Github for repositories by a keyword. Let’s create our test class and try to prepare an instance of the DefaultDataRepository. Note that,DefaultDataRepository constructor requires a DataSource as an argument. First, we will check the traditional approach of providing dependency and switch to a Dagger dependency later.

Here, we have a mock of the DataSource. Whenever we call the getSearchResponse() from DataSource, the mock will return a fake response. Our test needs to verify if the dataRepository.getSearchResponse() actually trigged the remoteDataSource.getSearchResponse() function with proper arguments.


  1. The test function is wrapped inside a runBlockingTest. It’s part of the kotlinx.coroutines.testlibrary and helps running any suspend function inside a test.
  2. Since we are using MockK, coEvery and coVerifyare specially designed to handle any suspend function.

Run the test, and it should succeed. So far, everything looks good.

Blending Dagger for the Unit Test

We already created a successful Unit test by using mocks. Our effort to create Dagger dependencies will never pay off if we can’t use them in the Unit test. Our goal is to access the following classes in Unit tests and use them as dependencies.

  1. Modules (To provide all of our dependencies)
  2. AppComponent (To host all modules and create the dependency tree)
  3. BaseApplication (To trigger the Dagger injection)

We will take one step at a time to make the solution.


We are only interested in AppModule. Since we have to change the behavior of the RemoteDataSource() function only. Let’s create a TestAppModule that provides the same type of DataSource() instance but a mock one.


We can use the same AppComponent from our app, but we might need to exclude or create a mock version of the Unit test modules. It would be wise not to mess up with the real AppComponent. We will make a TestAppComponent that extends from AppComponent but has some Unit test specific changes. Also, we need to create a function for passing an instance of the Test class. Dagger needs this to enable field injection for the Test class.


By default, BaseApplication will launch whenever we run our app on the device. Let’s not mess up with our real BaseApplication class and create a test class that extends it. This way, we will have a separate but the same type of Application class for the app.

But how can we load up the TestBaseApplication in our test?

Introducing the Test Runner

We can use a Unit test runner to load our Application class whenever the Unit test runs. We will create a new Rule class and extend it from the AndroidJUnitRunner.

Once the Test Runner is ready, let’s plug it into the build.gradle file.

Wrapping up the test class

We are close to the Dagger setup. Let’s prepare the Dagger injection inside the @Before method so that before each test, a new configuration will be ready. This way, changes in dependencies from one test won’t affect the logic in other Unit tests.

Now, we can update the test dependencies with @Inject annotation and re-run our test.

Abracadabra, We spelled our first magic with the potion.

Source Code

The source code for the article is available on Github.





Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +756K followers.

Recommended from Medium

🔍 Exploring Android Room Database with Room Explorer

Boost Your Kotlin Productivity With Extensions and Higher-Order Functions

App Caboodle is a New Personal App Organizer for Android

Guide to Understand HILT In Android

Awesome Features You Must Know in Android Studio Bumblebee

Why Are Kotlin Synthetics Deprecated and What Are the Alternatives?

Android Status bar colour

Jetpack Compose Ep:7 — Extended Floating Action Button App

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Prokash Sarkar

Prokash Sarkar

An Audiophile and Android enthusiast. Currently pursuing a perfect blend of style and function for a wide range of Android Applications.

More from Medium

Android — Intercept POST form data inside of WebView

How to Intercepter HTTPS on Android With Requestly SDK

Jetpack Compose Basics

Registering dependencies in Dagger 2