Mock Retrofit Response In Android

An easier way is to ask the backend developer to create the API service and just send fake content for the sake of it. The underlying notion is that we are not backend developers and it is not our responsibility to provide the endpoint.

In this article, we’ll explore the option which involves using Interceptors offered by OkHttp to mock an API response. It’ll allow you to test your Retrofit REST service interface without changing anything on the code.

Interceptors

Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls. Here’s a simple interceptor that logs the outgoing request and the incoming response.

interface Interceptor {
    @Throws(IOException::class)
    fun intercept(chain: Chain?): Response?
    interface Chain {
        fun request(): Request?

        @Throws(IOException::class)
        fun proceed(request: Request?): Response?

        @Nullable
        fun connection(): Connection?
    }
}

Interceptors from OkHttp are bad-ass and more powerful than you can think. They can be used in many different ways starting from logging in to monitoring the network calls our app makes and handling nasty situations. It allows you to rewrite requests to compress them or sign them or even transform the response body to workaround server problems.

In order to find a solution to our problem, we are prepared to deal with the consequences of rewriting the response body because we are making a conscious call.

Mock API Response Example

Creating the Mock Interceptor

Create a new class “MockInterceptor” and implements Interceptor on it. This will force the API response to use our own response to the API call.

class MockInterceptor : Interceptor{
    
    override fun intercept(chain: Interceptor.Chain): Response {
            val uri = chain.request().url().uri().toString()
            val responseString = when {
                uri.endsWith("login") -> getListOfReposBeingStarredJson
                else -> ""
            }

            return chain.proceed(chain.request())
                .newBuilder()
                .code(200)
                .protocol(Protocol.HTTP_2)
                .message(responseString)
                .body(
                    ResponseBody.create(
                        MediaType.parse("application/json"),
                    responseString.toByteArray()))
                .addHeader("content-type", "application/json")
                .build()
    }
}

const val getListOfReposBeingStarredJson = """
{"name":"velmurugan","address":"Chennai 600096"}
"""

Create API Client

In this case, I use Retrofit so I need to define its OkHttpClient explicitly to MockInterceptor onto it.

In this tutorial, I am not explaining the retrofit in detail. check my other post for more detail on retrofit.

interface ApiService {

    @GET("login")
    fun login() : Call<LoginResponse>

}


object NetworkClient {

    fun create() : ApiService {

        return Retrofit.Builder()
            .client(OkHttpClient.Builder().addInterceptor(MockInterceptor()).build())
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl("http://www.mocky.io/v2/")
            .build().create(ApiService::class.java)

    }

}

We are done with the mock interceptor and API client setup. The next, step is to call the API from our main activity and display the mock data.

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        NetworkClient.create().login().enqueue(object: Callback<LoginResponse>{
            override fun onFailure(call: Call<LoginResponse>, t: Throwable) {
                Log.d("Error",t.toString())
            }

            override fun onResponse(call: Call<LoginResponse>, response: Response<LoginResponse>) {
              Log.d("Success",response.body().toString())
            }
        })

    }
}

Mock API on Debug Mode Only

To mock the API only on debug mode, we need to check the BuildConfig is debug. If it’s debugging mode then we can return the mock response.

class MockInterceptor : Interceptor{

    override fun intercept(chain: Interceptor.Chain): Response {
        if (BuildConfig.DEBUG) {
            val uri = chain.request().url().uri().toString()
            val responseString = when {
                uri.endsWith("login") -> getListOfReposBeingStarredJson
                else -> ""
            }

            return chain.proceed(chain.request())
                .newBuilder()
                .code(200)
                .protocol(Protocol.HTTP_2)
                .message(responseString)
                .body(
                    ResponseBody.create(
                        MediaType.parse("application/json"),
                    responseString.toByteArray()))
                .addHeader("content-type", "application/json")
                .build()
        } else {
            //just to be on safe side.
            throw IllegalAccessError("MockInterceptor is only meant for Testing Purposes and " +
                    "bound to be used only with DEBUG mode")
        }
    }
}

Conclusion

This mock API response method is very useful when we have some issue with the API’s response. Also, useful test different response types without much effort.

Thanks for reading. let me know your feedback in the comments. Also, you can download this example from GITHUB.

Leave a Reply

Your email address will not be published.