How to inject mock dependencies into Android components using Dagger AndroidInjector
A couple of days ago I digged up my old project to try out the new Architecture Components on it, but first I wanted to refactor it a little, since it is more than one year old.
The first thing I did is to change the Dagger configuration to use the new AndroidInjector. This is a relatively new feature from the dagger-android library to remove even more boilerplate code. If you are not familiar with it, you can read about it on the official site. You can also check this commit in my repository, it’s pretty simple.
As I expected my UI tests failed to build after the changes. First let’s see how it looked like before, and what caused the problems.
In the previous implementation I had a reference to the
component in my Application class, so it was easy to substitute it with a test component by assigning the field in the test. I have previously written an article about this, you can check it out here:
Complete example of testing MVP architecture with Kotlin and RxJava — Part 3
Creating UI tests with fake data using Espresso.
With the new implementation this is not possible, because we don’t have a reference to the component. The
DaggerApplication superclass takes care of the injection instead of us.
This is how the new implementation looks like. Much simpler, and less boilerplate, also less boilerplate in activities and fragments. But how can we test this?
Creating a TestApplication class
We can create a different Application class, that will be used for testing. In this case we won’t subclass the
DaggerApplication class, instead we will do the injection in the
setUp method of our test classes.
You can see one thing that is worth explaining in this snippet. We implement the
HasSupportFragmentInjector interface. This is the interface among many others (
HasServiceInjector , etc…) what is implemented by the
DaggerApplication class to inject provided dependencies into Android components. Since we only inject dependencies into Fragments, we don’t need to implement the other interfaces.
To use our
TestApplication in instrumented test we also need to create a custom test runner class and set it in our build.gradle file as the
testInstrumentationRunner in the
Now we have everything what we needed to inject mocked dependencies into our instrumentation tests. Let’s see how the
UserListFragmentTest class looks like after the modification.
You can see that we are doing a pretty similar thing, than in the first version of the class. We are creating the component, but instead of assigning it to the
component field in the original
CustomApplication class, we use it to inject the dependencies into the
Removing code duplication
There is still some room for improvement in this code. If we create many instrumentation tests, we will need to add the same piece of code to every test class. There must be a better way to do it.
We can create a
TestInjector class, what will get the
TestApplicationModule in its constructor and make the injection. We can use this class in our
setUp methods instead of writing the same code over and over again.
First I wanted to create a JUnit test rule, but the problem is that test rules are evaluated before the
setUp method, and we need to initialize our mocks first.
Making it even more flexible with default arguments
What happens when we have many dependencies provided by our
TestApplicationModule, but we only want to mock some of them?
We can create fake implementation of some dependencies and specify them as default arguments in the constructor of our
In this case we have the flexibility to only mock the dependencies, what we need. As you saw in the previous example, we only needed to mock the
Android instrumentation testing can be problematic, when we are using the new Dagger AndroidInjector, but there are only a couple of steps, what we need to do to make mocking possible:
- Create a TestComponent and a TestModule, that will provide fake dependencies.
- Create a TestApplication class, that implements the appropriate interfaces.
- Create a custom test runner, that will run our tests by using our TestApplication class.
Thanks for reading my article. If you want to check out the whole code, you can find it in the following Github repository.
Contribute to kozmi55/Kotlin-Android-Examples development by creating an account on GitHub.
If you liked it share it with fellow Android developers or give it a clap or two.
If you have any questions or suggestions leave a comment below.