Retrofit is a type-safe REST client for Android, Java and Kotlin developed by Square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp.
As the old mechanisms like creating MockClient
class and implementing it from Client
are not working anymore with Retrofit 2.0, here I describe a new way of doing that. All what you need to do now is to add your custom interceptors for OkHttpClient like it is shown below. FakeInterceptor
class just overrides intercept
method and in the case if application is in DEBUG
mode return given JSON.
public final class RestClient {
private static IRestService mRestService = null;
public static IRestService getClient() {
if(mRestService == null) {
final OkHttpClient client = new OkHttpClient();
// ***YOUR CUSTOM INTERCEPTOR GOES HERE***
client.interceptors().add(new FakeInterceptor());
final Retrofit retrofit = new Retrofit.Builder()
// Using custom Jackson Converter to parse JSON
// Add dependencies:
// com.squareup.retrofit:converter-jackson:2.0.0-beta2
.addConverterFactory(JacksonConverterFactory.create())
// Endpoint
.baseUrl(IRestService.ENDPOINT)
.client(client)
.build();
mRestService = retrofit.create(IRestService.class);
}
return mRestService;
}
}
public interface IRestService {
String ENDPOINT = "http://www.vavian.com/";
@GET("/")
Call<Teacher> getTeacherById(@Query("id") final String id);
}
public class FakeInterceptor implements Interceptor {
// FAKE RESPONSES.
private final static String TEACHER_ID_1 = "{\"id\":1,\"age\":28,\"name\":\"Victor Apoyan\"}";
private final static String TEACHER_ID_2 = "{\"id\":1,\"age\":16,\"name\":\"Tovmas Apoyan\"}";
@Override
public Response intercept(Chain chain) throws IOException {
Response response = null;
if(BuildConfig.DEBUG) {
String responseString;
// Get Request URI.
final URI uri = chain.request().url().uri();
// Get Query String.
final String query = uri.getQuery();
// Parse the Query String.
final String[] parsedQuery = query.split("=");
if(parsedQuery[0].equalsIgnoreCase("id") && parsedQuery[1].equalsIgnoreCase("1")) {
responseString = TEACHER_ID_1;
}
else if(parsedQuery[0].equalsIgnoreCase("id") && parsedQuery[1].equalsIgnoreCase("2")){
responseString = TEACHER_ID_2;
}
else {
responseString = "";
}
response = new Response.Builder()
.code(200)
.message(responseString)
.request(chain.request())
.protocol(Protocol.HTTP_1_0)
.body(ResponseBody.create(MediaType.parse("application/json"), responseString.getBytes()))
.addHeader("content-type", "application/json")
.build();
}
else {
response = chain.proceed(chain.request());
}
return response;
}
}
Source code of project on GitHub
I decided to try method 1 as follows
public class MockClient implements Client {
@Override
public Response execute(Request request) throws IOException {
Uri uri = Uri.parse(request.getUrl());
Log.d("MOCK SERVER", "fetching uri: " + uri.toString());
String responseString = "";
if(uri.getPath().equals("/path/of/interest")) {
responseString = "JSON STRING HERE";
} else {
responseString = "OTHER JSON RESPONSE STRING";
}
return new Response(request.getUrl(), 200, "nothing", Collections.EMPTY_LIST, new TypedByteArray("application/json", responseString.getBytes()));
}
}
And using it by:
RestAdapter.Builder builder = new RestAdapter.Builder();
builder.setClient(new MockClient());
It works well and allows you to test your json strings without having to contact the real server!
Testing JSON deserialization to your objects (presumably with TypeAdapters
?) seems like a separate problem that require separate unit tests.
I use version 2 personally. It affords type-safe, refactor-friendly code that can be easily debugged and altered. After all, what good is declaring your API as interfaces if you aren't creating alternate versions of them for testing! Polymorphism for the win.
Another option is using a Java Proxy
. This is actually how Retrofit (currently) implements its underlying HTTP interaction. This will admittedly require more work, but would allow for much more dynamic mocks.
You can also use something like Webservermock from Squareup! --> https://github.com/square/okhttp/tree/master/mockwebserver
I am a big fan of Apiary.io for a mocking an API before moving to a real server.
You could also use flat .json files and read them from the file system.
You could also use publicly accessible API's like Twitter, Flickr, etc.
Here are some other great resources about Retrofit.
Slides: https://docs.google.com/presentation/d/12Eb8OPI0PDisCjWne9-0qlXvp_-R4HmqVCjigOIgwfY/edit#slide=id.p
Video: http://www.youtube.com/watch?v=UtM06W51pPw&feature=g-user-u
Example Project: https://github.com/dustin-graham/ucad_twitter_retrofit_sample
Mockery (disclaimer: I’m the author) was designed just for this exactly task.
Mockery is a mocking/testing library focused on validating networking layers with built-in support for Retrofit. It auto-generates JUnit tests based on the specs of a given Api. The idea is not to have to write manually any test; neither implementing interfaces for mocking server responses.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With