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!