Retrofit testing, callbacks?

1.3k Views Asked by At

I'm trying my best to learn how to properly test my Android apps. Now I usually use the following structure:

  • Model
  • Retrofit (letting it handle the threading by using callbacks)
  • Wrapper for retrofit calls that posts events on success and failure to be picked up by presenters.
  • Presenters.
  • Views.

I've tested apps before where I handled the threading myself. In this case I have no idea on how to verify if my wrapper is actually calling event posting methods because those methods are called on callbacks. What can I do to solve this problem?

The only solution I can come up with is not using the callbacks, but they are SO convenient. Isn't it a step back to handle things myself just for the sake of testing?

I can only guess my ways of architecting this are poor for testing.

EDIT: This question suggests that it's a good idea to split the testing as:

1.- Test that your async process is submitted properly. You can mock the object that accepts your async requests and make sure that the submitted job has correct properties, etc. 2.- Test that your async callbacks are doing the right things. Here you can mock out the originally submitted job and assume it's initialized properly and verify that your callbacks are correct.

But how can I test the first part without mocking the Retrofit service (because one should never mock third party code)?

2

There are 2 best solutions below

3
On BEST ANSWER

Try using Rx with Retrofit. It makes the synchronous Rx requests as Asynchronous thus avoiding the need for callbacks. What's more is you get perfect callbacks from the Rx mechanism which will help you test properly.

Look into RxJava with Retrofit

0
On

Retrofit asynchronous callbacks can be tested by creating an adapter with a synchronous executor.

In the adapter factory I use the below method to create a Retrofit adapter for testing with Robolectric and WireMock. WireMock acts as server on the baseURL and returns the responses for the requests on the REST API via Retrofit.

public static RestAdapter synchronousAdapter(Context context, String baseUrl) {
    RestAdapter.Builder builder = initiateBuilder(context);
    builder.setEndpoint(baseUrl);
    Executor synchronous = new SynchronousExecutor();
    builder.setExecutors(synchronous, synchronous);
    return builder.build();
}

private static final class SynchronousExecutor implements Executor {
    @Override public void execute(Runnable r) {
        r.run();
    }
}