Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test a REST API that uses Retrofit and Dagger2

I would like to create a unit test that verifies that the API successfully gets the List of Repos. I would like that the test actually makes the network connection instead of using a Mock Server. And also, would be good to use RoboElectric for example so the test can run on the JVM.

This to test the Model from the MVP architecture.

I am using a sample project from Mosby, this uses Dagger 2 and Retrofit 1.9.

public interface GithubApi
{
    @GET("/repositories")
    @Headers("Cache-Control: no-cache")
    public void getRepos(Callback<List<Repo>> callback);
}

This is the module:

@Module()
public class SampleModule
{
    @Provides @Singleton public GithubApi providesGithubApi()
    {
        OkHttpClient client = new OkHttpClient();
        client.setCache(new Cache(context.getCacheDir(), 10 * 1024 * 1024));

        RestAdapter restAdapter = new RestAdapter.Builder()
            .setClient(new OkClient(client))
            .setEndpoint("https://api.github.com")
            .build();

        return restAdapter.create(GithubApi.class);
    }
}
like image 922
Kenenisa Bekele Avatar asked Jan 25 '16 22:01

Kenenisa Bekele


2 Answers

What do you actually want to test? I'm asking because it seems that you are not clear what you actually want:

  • Testing an API? It's the job of the backend to provide a fully working API.
  • Testing that your app is doing http communication correctly? That sounds that you want to test Retrofit. But Retrofit is already tested. You can assume that retrofit works and you don't have to test it again.
  • Testing that json is parsed correctly? That's already don by jackson or gson that is used internally by Retrofit. Again, there is no need to test that again.

So still the same question: what do you actually want to test on "Model" (business logic layer in MVP)? If retrofit is your whole business logic, than the following things (not already tested by external libraries as mentioned above) can be tested:

  • Are your POJO classes annotated correctly so that gson / jackson is deserializing the json received from Github API correctly. How to do that? In that case you need reliable mocked data and can not use live API. In that case you have to mock the server response. Otherwise you can't write a unit test because GithubApi will return different data if you run your test again tomorrow.
  • You can test if you handle all http response codes correctly in your app. However, you also have to mock Github API, otherwise you can't simulate that Github API is returning a 404 response, or 401 etc.

So that are the kind of unit tests you can write for a Unit testing the "model" if your model is just retrofit.

I would like that the test actually makes the network connection instead of using a Mock Server.

I hope that you now understand that there is a need of a MockServer.

Otherwise it sounds that you want to write a kind of integration test. But again, what do you actually want to test with that integration test?

To me it seems that you just want to ensure that your app is not crashing when loading data from GithubAPI and scrolling in a list of items in your UI, right?

So such "integration tests" can be written with both Robolectric and Espresso. But, that's actually not a test! do you have any assertEquals() etc in such a test? So it's a pretty dumb test because you can't verify nothing except that your app is not crashing. If that is what you are looking for, go ahead, write an Espresso test for your activity that loads live data and scrolls your recylcerview all the way down until the end. But you actually have covered pretty nothing with such a test. It's not reliable, reproduceable and only verifies that your app is not crashing in the "happy path". But that's pretty the same as doing it manually when launching the app.

So ask yourself: What do I want to test? What actually should I test? As said, testing retrofit doesn't make sense because it's already tested by square. Testing that scrolling a RecyclerView works doesn't make sense either because the UI widget RecyclerView is already tested internally in the android framework.

like image 148
sockeqwe Avatar answered Oct 16 '22 22:10

sockeqwe


The keyword you are searching for is integration test. Integration tests are always tricky (since you rely on internet connection, tests can be flaky), and I'd suggest you to work on it after you are done with all the unit and UI tests. Here are two links that might be useful for you:

  • http://mdswanson.com/blog/2014/02/24/integration-testing-rest-apis-for-android.html
  • https://www.reddit.com/r/androiddev/comments/2ujj55/retrofit_not_doing_http_request_during_unit_test/
like image 30
iamkaan Avatar answered Oct 16 '22 23:10

iamkaan