Android : Mock Response with Retrofit & OkHttp

Romman SabbirRomman Sabbir
3 min read

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

What is Mock Server?

A mock API server or mock server API imitates a real API server by providing realistic mock API responses to requests. They can be on your local machine or the public Internet. Responses can be static or dynamic, and simulate the data the real API would return, matching the schema with data types, objects, and arrays.

Why API Mocking?

A mock API server is useful during development and testing when live data is either unavailable or unreliable. While designing an API, you can use mock APIs to work concurrently on the front and back-end, as well as to gather feedback from developers.

You can also use mock APIs to emulate APIs you don’t control. For example, you can use a local mock server to fake results from a public API when you aren’t connected to the Internet. Or, use mock data responses if live calls to an API would incur a charge from the provider.

How to Mock API Response with OkHttp and consume with Retrofit?

We can simply acheive mocking API response with the help of OkHttp and how? By using Interceptor from OkHttp. OkHttp provides a way to intercept during every network operation requested by Client (Android Application).

Practical Example?

Let's say, we want to call an api endpoint called fake-login. This API endpoint should return an response (Error or Success). But at this moment, we just received an JSON as response from the Backend Engineering Team and APIs still under development.

In this scenario, we can be benefited by OkHttp. We can intercept during the network operation and ask OkHttp to return a Mock Response for an/some API endpoints.

Let's get into the coding part 😁

object APIProvider {
    //Return a lazy instance of OkHttp client
    private val myHttpClient: OkHttpClient by lazy {
        val ins = OkHttpClient().newBuilder()
            .connectTimeout(1, TimeUnit.MINUTES)
            .readTimeout(1, TimeUnit.MINUTES)
            .writeTimeout(1, TimeUnit.MINUTES)
            .retryOnConnectionFailure(true)
        ins.build()
    }

    //Public access point for Mock API Service
    fun getMockAPI(): MockAPIEndpoint = retrofitInstance.create(MockAPIEndpoint::class.java)

    //Return a lazy Retrofit instance
    private val retrofitInstance: Retrofit by lazy {
        Retrofit.Builder()
            .baseUrl("https://rommansabbir/api/v2/")
            .client(myHttpClient)
            .build()
    }
}

We have an Singleton Object called APIProvider, which expose an public function to get access of MockAPIEndpoint. Lets take a look at the MockAPIEndpoint.

interface MockAPIEndpoint {
    @GET("fake-login")
    fun login(): Call<ResponseBody>
}

MockAPIEndpoint has only one API at this moment and we want to return a mocked JSON object as Response.

Now, lets work on our LoginInterceptor class.

class LoginInterceptor: Interceptor{
    override fun intercept(chain: Interceptor.Chain): Response {
        //If requested endpoint matched to targeted endpoint, we will return an mocked response.
        if (chain.request().url.toUri().toString().endsWith("fake-login")) {
            val responseString = "OUR_JSON_RESPONSE_FROM_ASSET_OR_OTHER_SOURCE"
            return chain.proceed(chain.request())
                .newBuilder()
                .code(200)
                .protocol(Protocol.HTTP_2)
                .message(responseString)
                .body(
                    responseString
                        .toByteArray()
                        .toResponseBody(
                            "application/json".toMediaTypeOrNull()
                        )
                )
                .addHeader("content-type", "application/json")
                .build()
        } else {
            //Skip the interception.
            return chain.proceed(chain.request())
        }
    }
}

Here, we are intercepting during the API request. If requested endpoint matches to our targeted endpoint, we will return a mocked JSON object as response. We can get this JSON from Asset or other source (eg. String).

We are almost done with our API Mocking. Let's add our LoginInterceptor to OkHttpClient. Update APIProvider::myHttpClient as shown down.

    //Return a lazy instance of OkHttp client
    private val myHttpClient: OkHttpClient by lazy {
        val ins = OkHttpClient().newBuilder()
            .connectTimeout(1, TimeUnit.MINUTES)
            .readTimeout(1, TimeUnit.MINUTES)
            .writeTimeout(1, TimeUnit.MINUTES)
            .retryOnConnectionFailure(true)
        //Adding our LoginInterceptor only on Debug mode only
        if (BuildConfig.DEBUG){
            ins.addInterceptor(LoginInterceptor())
        }
        ins.build()
    }

That's it. Now, when we want to execute an API request to the targeted endpoint with Retrofit, OkHttp will return Mock API Response.

GIST?

https://gist.github.com/rommansabbir/7fc13de4f910283854d0c7ca475e98c0

Happy Coding...

0
Subscribe to my newsletter

Read articles from Romman Sabbir directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Romman Sabbir
Romman Sabbir

Senior Android Engineer from Bangladesh. Love to contribute in Open-Source. Indie Music Producer.