****Update****

In Dagger 2.19 some of the APIs have been changed (https://github.com/google/dagger/releases/tag/dagger-2.19) so I have updated the code snippets

A few months ago I have written about how to test Activity that uses Dagger’s AndroidInjector in an Espresso test. The solution worked well for an Activities but if you’re using Fragments, this might add additional complexity, as always, and we need to refine the solution in order to test Fragments.

Fragment’s Fields Injection

Activity Injection is simple, Dagger will create an AndroidInjector out of your configuration and it will be in the Application level, but Fragment’s AndroidInjector can be in the Application level, Activity level or Fragment level (as a child Fragment). The level depends on which Component / SubComponent the Fragment’s module will be declared.

Activity Level Fragment Injection

In this post we will focus on what I believe is the common use case, Fragment injection in the Activity level, we will use the same sample app from the previous post and the same test but this time with Fragment in addition to Activity and the Fragment will be our View.

The sample app

A quick recap on the sample app, we have View with TextView and FAB, the default text is “hello world” and upon clicking on the FAB the text should be changed to “Fab was clicked”. When the FAB is clicked we delegate it to the Presenter which as the response will ask the View to change the text. The View this time will be Fragment instead of Activity as in the previous post.

The application structure

How to Test The Fragment?

The plan is to obtain the Application level injector, it will be taken from the Application object, save it and replace it with our fake AndroidInjector. We will create a function that gets a single parameter, lambda with MainFragment receiver, this receiver will have code that initiates the properties that we want to inject, in our case mock of the Presenter.

First, we get the Application injector which holds map between all Activities and their factories which create the Activities member injection, then we will save the original injector of host Activity of the Fragment and apply the original Application level injector. Next step is to create Fragment injector that will inject the original Activity injector except for the Fragment under test, for this Fragment it will call to the lambda with MainFragment receiver so will init the inject properties with the mock instance.

Create fake injector

Now we can use this function in our test in the following way:

The test

Conclusions

In the previous post we saw how simple is to test Activity using Espresso and Dagger and now we also saw how to test Fragment with minimal overhead and hopefully, this will help you write better tests

Happy testing!!