Android : Mock Response with Retrofit & OkHttp
Tags: android, api, beginners, mobile
Published: 2022-10-22 04:49:20

## 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.