Unit Testing in Android is a mess

Chirag Jain Blocked Unblock Follow Following Mar 17, 2017

Unit Testing in Android is pretty tricky. There are many articles which have concluded this, like Why Android Unit Testing is so Hard.

In a development process, the first problem appears when one writes a test-case using an android component. One will realize that this problem cannot be solved with JUnit alone, one has to write an Android Instrumentation Test which will require a physical device (or an emulator) to run a simple test case. (Why so ?)

What is the problem in using a device? The answer is simple. When you have around 1000 unit-tests to test, one needs to wait for hours just to see if the simple logic which doesn’t have any functional test cases is running without a glitch.

So there are two possible solutions available for this problem, first is to use Roboelectric and other is to inject android dependency and mock it by using Mockito.

Robolectric is a unit test framework that de-fangs the Android SDK jar so you can test-drive the development of your Android app. Tests run inside the JVM on your workstation in seconds.

While using Roboelectric, the biggest problem I faced is version compatibility. Development of Roboelectric is slower than the actual android development. So when I was working on api level 21, Roboelectric had support till api level 18. In Parallel there are many other problems, like it is slower than pure JUnit testing and doesn’t support native libraries.

Another way is to inject android dependency and mock it at the time of testing. Same solution is provided in this android documentation. But there are two problems, neither you can mock everything nor is it easy to test android activity in a standard way.

Solution is simply architectural, one needs to make their business logic independent from android component so that it can be tested with JUnit. But how? When we develop android apps, how can we make sure that the logic is independent of android components. The solution is to follow a SOLID architectural pattern through which one can make his code more readable, scalable and testable.

Android doesn’t enforce you to follow MVVM, MVP or any of the layer segregation patterns. It just provides an activity class to play with many different android component like resources, preferences and intents etc.

Android provides two different type of testing environment, one is local and other is instrumented. Some developers wants to cover maximum of their code by local unit testing for obvious reasons. So what they do is basically try to make android development more structural. So, they use different external libraries and create a pattern of their own. Some of the implementations are Uncle bob’s clean architecture implementation, talk by Richa Khandelwal and case study by Lyubomir Ganev. These guys tried to solve the problem of testing as well as making android code more segregated by modern design principles.

I would highly recommend one to read about Uncle Bob’s Clean Architecture and Dependency Rule to understand the advantages of a clean code design.

What I want?

Segregation of different layers is one thing which I want to achieve. Writing all of the code in an activity is not what I or anybody else prefers. Segregation will increase code coverage and also makes testing a lot more easier.

What I did?

Obviously reinventing the wheel is not a good approach, so the first thing I did was to start reading the solutions provided by others. As I deep dived into the problem, I came to know that the problem still exists in one or the other form. There are few implementation in which people were able to segregate layers like MVP or MVVM or VIPER. In most of them, they ended up passing the activity as a dependency to the presenter, which again makes a dependency on an android system, thus violating the dependency rule.

Dependency Rule inspired by Uncle Bob’s Clean Architecture

What should one should do to solve this problem? So, I commenced with simple VIPER architecture and tried to solve different problems by focussing on how the make presenter testable using only local unit test-cases.

As per VIPER with some customization, we have following components -

View : Activity, Fragments, Dialog Fragments etc. Presenter : Presenter will contain all view logic and generate a view-model and provide it to the view. With any action on view, view-model can be updated by presenter. View-Model : It is a POJO which represents our view. Interactor : It will take care of different data sources like database, network etc. It will also contain business logic. It will provide data like location, sensors etc. from android system-services. All the data will be provided in the form of an entity. Entity : It is a POJO for our data. Navigator : It will contain methods like finish, showToast, startActivity, showProgressDialog etc. This class will be injected in presenter for routing and android related events. This will be mocked at the time of testing presenter. Prefs and Resource Provider : Prefs is a wrapper class for preferences whereas ResourceProvider is a wrapper class for resources. These classes can be injected in presenter as per the requirement and can be mocked at the time of testing presenter.

For achieving this, I have used the following libraries -

Dagger 2 : For facilitating dependency injection. RxJava 2 : For communicating between different layers. It can do a lot besides communication (Please start using it by today if you aren’t already using it). Switched from Volley to Retrofit 2 : Many reasons for doing so. But one important reason is that it supports RxJava 2. Also interfaces are great for testing.

Now before jumping to code, I want you to understand the purpose and basic functionality of above described libraries. For Implementation go to the next part of this tutorial.