Testable classes don't seek, but receive

13 July 2015

An Android example on how to use Dependency Injection with Dagger and mock dependencies in JUnit with Mockito

There is a phenomenon in Hollywood from the cliché response given to amateurs auditioning: "Don't call us, we'll call you". My friend Mauricio Aniche wrote a great post about how to use this concept in order to have better unit tests.

We're going to apply here the same code he wrote. In a pratical way, let's understand how to use the Inversion of Control pattern in Android applications.

Warming up: The Scenario

We have a BillFilter responsible for filter bills that have value less then 2000. This class will receive the BillDao in the constructor.

Our BillDao will connect to the database. The BillFIlter will be responsible for the logic of getting just the values with less then 2000 values. The BillFilter will receive BillDao as a parameter in the constructor. The MainActivity will get the number and show in the screen.


Dependency Injection with Dagger 2

As you can see in the first code above, BillFilter's constructor has now @Inject annotation. This comes from JSR-330 specification and will be implemented with Dagger 2 in this example.

In order to have this injection working properly, we need to teach Dagger what to inject when constructin the graph. For this, we'll need to use 2 components of the framework:
  • ❱ Module: To teach how to provide one dependency
  • ❱ Component: Tie everything together and return full loaded object
With this classes, Dagger will look the dependency in the BIllFilter constructor and search for a methods annotated with @Provides. Component is the class we will use when we need a BillFilter from now on.

The Activity

The activity now will be very simple. The idea is just to use fully loaded BillComponent and receive the filtered bills with ther filter method. We then update the TextView with the list size.

Finally, we can easily test

The main idea here was to receive dependencies as parameters, for example, in the constructor. This way we can achive loose coupling in our design and unitarily test our bussiness logic.

In the test bellow, everything we want is to make sure the filter method will every works as expected. Here comes Mockito. Benefited from the idea of receiving the BillDao dependency in the constructor, we will mock BillDao and stub the all() method to return a controled list. This way, we don't need a database to unit test the scenario.

Don't seek, receive

Using the idea of receiving dependencies you can easily make your code more testable. To achive that, try to use a framework like Dagger or any one else. The most important concept here, as explaind in the post, is to have a good classes design in order to have good and maintainable software.

comments powered by Disqus