Retrofit – Mock service with an interceptor

Share

Share on facebook
Share on whatsapp
Share on linkedin

Many times, when starting a new project, we find that we still do not have a backend prepared to cover the needs of the frontend. In this case, how do we avoid slowing down development? Well, here we share you a possible solution to this scenario.

The ideal way to proceed in this case is to make a contract walidated by both the backend engineer and the frontend.

Now we are ready to start!

A real scenario

Usually we could imagine the json structure to create ours classes and write it down into a text file. But we can do it more real calling retrofit to emulate the complete scenario. To make it we might use an Interceptor implementation. 

Make a class called MockInterceptor and implement the interface Interceptor. Then you should override the intercept method. Inside this method and before doing anything, make sure you are only doing it for debug, to avoid using a mock in production

var response: Response? = null
if (BuildConfig.DEBUG) {

} else { // if not DEBUG proceed normally
    response = chain.proceed(chain.request())
}
return response

 

Well, to get up the json file we add this to the assets folder. For example, we will create an example folder and inside it another folder call target. Finally inside the target folder, create a service json file. The full path would be look like this: «assets/example/target/service.json». This means that our service it’s «https://www.example.com/v1/example/target/service Remind https://www.example.com/v1/» it’s our default service url.

So the json files will be taken from the end of the base url as a folder structure.

Reading the json file

Once the file corresponding to the service to be mocked has been created, you need to read it from the assets and provide it to your response.

private fun getJsonDataFromAsset(context: Context, fileName: String): String? {
    val jsonString: String
    try {
        // Append the json extension
        jsonString = context.assets.open("$fileName.json").bufferedReader().use { it.readText() }
    } catch (ioException: IOException) {
        ioException.printStackTrace()
        return null
    }
    return jsonString
}

 

And use it in the intercept method, inside the debug condition, to send it as a response.file

override fun intercept(chain: Interceptor.Chain): Response {
    var response: Response? = null
    if (BuildConfig.DEBUG) {
        // Get Request URI.
        val uri: URI = chain.request().url.toUri()
        // Get path String.
        var path: String = uri.path
        // Remove the starter slide '/'
        path = if (path.startsWith('/')) path.substring(1) else path
        // Get the json file text
        val responseString: String = getJsonDataFromAsset(context, path).orEmpty()

        // Create the response
        response = Response.Builder()
            .code(200)
            .message(responseString)
            .request(chain.request())
            .protocol(Protocol.HTTP_1_0)
            .body(ResponseBody.create("application/json".toMediaType(), responseString.toByteArray()))
            .addHeader("content-type", "application/json")
            .build()
    } else {
        response = chain.proceed(chain.request())
    }
    return response
}

 

Modify your «ServiceFactory» class to accept the mock interceptor option:

class ServiceFactory(private val context: Context, private val shouldUseMock: Boolean) {

 

and the okHttpClient method:

private fun okHttpClient(): OkHttpClient {
    var client = OkHttpClient.Builder()
    client = addMockInterceptor(client, context, shouldUseMock)
    return client.build()
}

 

Finally add the method to pass the interceptor to the okhttp client:

private fun addMockInterceptor(builder: OkHttpClient.Builder, context: Context, shouldUseMock: Boolean): OkHttpClient.Builder {
    if (BuildConfig.DEBUG && shouldUseMock) {
        val mockInterceptor = MockInterceptor(context)
        builder.addInterceptor(mockInterceptor)
    }
    return builder
}

 

That’s all! Now we have an interceptor to mock a service. Use it passing the variable «shouldUseMock» in true, like this:

ServiceFactory(this, true).createInstance(ServiceOne::class.java)

Do you want to develop your next AR project with us? Contact us!

Related Posts

image of a man working with a PC

Retrofit – Multiples base urls with annotations

When we create a new application, we will probably have multiple API calls. And probably some of them will be …

HobbiesUp-ThinkUp

“Work is life and life is work”: No, thanks 👋.

Although some say work is life and life is work, the truth is that balancing your professional and personal life …

Top Developers App - ThinkUp Team

AppsUp: Getting cozy with some of the people that are behind the scenes

They are the ones making the magic happen, but what do they think about other apps? What are their preferences? …

flag
United States
1330 Lagoon Ave. Minneapolis, MN 55408
(408) 457-4075
flag
Uruguay (HQ)
Dr. Mario Cassinoni 1011, 11400, Montevideo.
(+598) 45622769