“A two-display workspace with lines of code on one of the monitors” by Farzad Nazifi on Unsplash

Writing Testable Code for Android Apps

Ismail Khan
5 min readMay 1, 2018

Writing testable code is an art. Just like any other art, if you want to master it then you have to practice it. Same goes for software development but they are some concepts you need to understand first. If you are into software development then you must have definitely come across the term Dependency Injection(DI). Any software which does not make use of this will end up being difficult to maintain and more importantly difficult to unit test.

In software engineering, dependency injection is a technique whereby one object (or static method) supplies the dependencies of another object. A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it. The service is made part of the client’s state.[1] Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.

Above is the definition of DI that you will find on wiki. An object provides dependency to another object. If this confuses you don’t worry, we will go through an example(for Android) which will make it clear to you.

Most of our Android app will connect to a server via an API and also connect to a local DB. Lets say we have a class ApiService.java which handles all the network operation. For the purpose of simplicity, we will create a method which would return just a String. But you can assume that we are fetching it from a server, but we will just be returning a simple String(Shhhhh!).

Next we will have a class called MyDatabase.java which will cache the data returned from our ApiService class locally. This class will be responsible for storing and retrieving of data. Usually you will have an instance of DB or SharedPreference, but again for simplicity we will just have a String object which will store the String returned from our ApiService class.

In mobile development you must have definitely come across the term “Offline First”. Which is being able to provide data to the user as fast as possible even if the device is not connected to the internet/slow internet. Thats the reason we cache the String in our MyDatabase class which is returned from our ApiService class(in our example the ApiService class does not need an internet connection as we are just returning a String but in a real world example it will need an internet connection to fetch that String).

How offline first works is that we will first try to display the cached data to the user and then in background fetch the data from our server via an API. Usually server response might take some time to return data back to us, depending on the amount of data and network connectivity, so the user may have to wait for the data to be returned. But if there is cached data they can start viewing the data immediately without delay or seeing a loading icon, and incase the device is not connected to the internet the user wont see a blank screen but instead will continue viewing the cached data(ofcourse this will only work when there is some data in our cache and this will happen only when our API successfully returns data atleast once).

So lets create another class called Repository.java. Now this is where we need to be careful as most of inexperienced developer (unaware developers) would do something like below.

Creating a class like above is bad as we wont be able to mock our ApiService class and MyDatabase class for testing. Also, in future if we change ApiService class creation, lets say, it accepts a HttpClient object as its constructor parameter like below

new ApiService(httpClient);

then we would have to change it into our Repository class as well. The important thing here to remember is that Repository class should not care how ApiService and MyDatabase instances are created. So the correct way would be as below.

Now, our Repository class becomes easy to test it. In our test class we can easily pass mock ApiService and MyDatabase objects to Repository class and test it. Excellent!.

Now we will add a method to our Repository class which would first return cached data from our MyDatabase class (if present) and then fetch live data from our ApiService class and store that live data in the database.

Here Callback is an interface which will be implemented by any class which needs that String. The interface has two methods:

  • public void cacheData(String data);
  • public void liveData(String data);

Any class which implements the Callback interface needs to implement these two methods. I think both the method names are self explanatory as what their intended purpose is.

Complete Repository class looks like below.

As you can see Repository is a Singleton class which is correct as we need only one instance throughout the application. Good! Now lets say we want to show that String on our screen then we would first implement Callback interface in our Activity/Fragment. In our case it would be Activity

When you run your app you should see a nice and beautiful “String from API” message on your screen. At this point your code is now fully testable.

So how do we test it?. Easy!

First add the below line in your module’s build.gradle file .

Next, go over to your androidTest package and create a test class called MainActivityTest.java and add below code.

So whats happening here ?. The below code

holds the activity from launching immediately and gives us the opportunity to mock our dependencies.

Below method annotated with @Before will be called every time before any other method annotated with @Test is called. Here we are creating an instance of Repository class. As its a Singleton class same instance will be used in our MainActivity class as well.

Next is our test method. As the method name say, we checking if the fetched data is shown on the screen or not(using Espresso).

Thats it. You have now written testable code. Congrats!

You can download the complete code from below github link.

One issue with this approach is the boilerplate code present in MainActivity. We need to create instances of ApiService and MyDatabase class every time we need an instance of Repository class. If we need Repository instance, lets say, in SecondActivity we need to again write below code.

We can avoid it using Dagger2. Will look into it in next article. Till then Cheers!

--

--