Android: Network Calling with Retrofit and Unit Testing

Android: Network Calling with Retrofit and Unit Testing

How to Unit Test Network Calling in Android with the power of Retrofit

If get to know something new by reading my articles, don't forget to endorse me on LinkedIn

What is Retrofit?

Retrofit is a type-safe REST client for Android, Java and Kotlin developed by Square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp.

Detail about Retrofit & How it works

What is Unit Testing?

Unit Testing is a type of software testing where individual units or components of a software are tested. The purpose is to validate that each unit of the software code performs as expected. Unit Testing is done during the development (coding phase) of an application by the developers. Unit Tests isolate a section of code and verify its correctness. A unit may be an individual function, method, procedure, module, or object.

More about Unit Tesing

What will be our Acheivement?

We want to acheive some basic testing for this article.

  • First, we will have an instance of Retrofit object which contain a valid BASE_URL and in Test, we will make sure that the BASE_URL Retrofit has, is same as our's BASE_URL

  • Second, we will create Endpoint and Service class for Retrofit, and we will test our First API Calling with Retrofit. In the Test, we will verify that API Execution return Success result.

Let's get into the coding part

First, let's create our Client Class that provide an instance of Retrofit Object with a valid BASE_URL

class RetrofitClient {
    val retrofit: Retrofit by lazy {
        Retrofit.Builder()
            .baseUrl(BuildConfig.BASE_URL)
            .addConverterFactory(MoshiConverterFactory.create())
            .build()
    }
}

When we call RetrofitClient().retrofit provider return an lazy instance of Retrofit.

Now, let's have our FIRST test of the Retrofit instance. We will check if the provided Retrofit instance have a BASE_URL that matches to our BASE_URL.

First Unit Test

For this test, Create a new Class called RetrofitClientTest under the test package.

class RetrofitClientTest {
    @Test
    fun testRetrofitInstance() {
        //Get an instance of Retrofit
        val instance: Retrofit = RetrofitClient().retrofit
        //Assert that, Retrofit's base url matches to our BASE_URL
        assert(instance.baseUrl().url().toString() == BuildConfig.BASE_URL)
    }
}

and, run the test.

✔️ Tests passed: 1 of 1 test - 438ms

BUILD SUCCESSFUL in 15s
28 actionable tasks: 16 executed, 12 up-to-date
8:02:23 PM: Tasks execution finished ':app:cleanTestDebugUnitTest :app:testDebugUnitTest --tests "com.rommansabbir.testing.RetrofitClientTest.testRetrofitInstance"'.

Fun, Right?.

Yeeeeee, we have our first Unit Test of Retrofit which verify that, the given instance of Retrofit contain a base url that exactly matches to our BASE_URL.

Now, Let's get into the API Testing part and we are creating our FIRST API Endpoint called PlacesEndpoint and it's implementation PlacesService.

interface PlacesEndpoint {
    @Headers("Authorization: ${BuildConfig.API_KEY}")
    @GET("places/nearby")
    fun getVenueRecommendations(@QueryMap query: Map<String, String>): Call<ResponseWrapper>
}
class PlacesService constructor(private val retrofit: Retrofit) :
    PlacesEndpoint {
    private val endpoint by lazy { retrofit.create(PlacesEndpoint::class.java) }
    override fun getVenueRecommendations(query: Map<String, String>): Call<ResponseWrapper> =
        endpoint.getVenueRecommendations(query)
}

Second Unit Test

Now, add a new test called testPlacesService() to our RetrofitClientTest class.

class RetrofitClientTest {
    @Test
    fun testPlacesService() {
        //Get an instance of PlacesService by proiving the Retrofit instance
        val service = PlacesService(RetrofitClient().retrofit)
        //Create a new request for our API calling
        val query = VenueRecommendationsQueryBuilder()
            .setLatitudeLongitude(52.376510, 4.905890)
            .build()
        //Execute the API call
        val response = service.getVenueRecommendations(query).execute()
        //Check for error body
        val errorBody = response.errorBody()
        assert(errorBody == null)
        //Check for success body
        val responseWrapper = response.body()
        assert(responseWrapper != null)
        assert(response.code() == 200)
    }
}

What we want to acheive?

To verify that Retrofit instance is provided by the respective provider. Initialize PlacesService and test the api execution is working as expected.

Now, run the test

✔️ Tests passed: 1 of 1 test - 574ms

BUILD SUCCESSFUL in 3s
28 actionable tasks: 2 executed, 26 up-to-date
8:54:14 PM: Tasks execution finished ':app:cleanTestDebugUnitTest :app:testDebugUnitTest --tests "com.rommansabbir.test.RetrofitClientTest.testPlacesService"'.

Super Fun, Right?

That's it for today. Leave your feedback :)