Comment mettre à l'essai des unités D'appels api Retrofit?

j'essaie d'intégrer des tests unitaires pour chaque morceau de code possible. Mais je suis confronté à des problèmes tout en ajoutant des cas de test pour les appels api qui sont fabriqués par retrofit.

le compilateur JUnit n'exécute jamais le code dans les fonctions de CallBack .

Il ya une autre option de faire tous les appels api synchrone à des fins de test, mais ce n'est pas possible pour toutes les affaires de mon application.

comment régler ça? Je dois ajouter des cas de test dans les appels api par n'importe quel moyen.

39
demandé sur halfer 2015-09-03 14:34:46

2 réponses

je teste mes callbacks Retrofit en utilisant les bibliothèques Mockito, Robolectric et Hamcrest.

tout d'abord, configurez la pile de lib dans la compilation de votre module.gradle:

dependencies {
    testCompile 'org.robolectric:robolectric:3.0'
    testCompile "org.mockito:mockito-core:1.10.19"
    androidTestCompile 'org.hamcrest:hamcrest-library:1.1'
}

À jour globale d'un projet de construction.ajouter la ligne suivante aux dépendances buildscript:

classpath 'org.robolectric:robolectric-gradle-plugin:1.0.1'

puis entrez le menu "construire des variantes" dans Android Studio( pour le trouver rapidement, cliquez sur Ctrl+Shift+A et cherchez-le), et basculer" test artefact " option à "Essais Unitaires". Android studio passera votre dossier test à " com.votre.package (test) " (au lieu d'androidTest).

Ok. La mise en place est faite, il est temps de faire quelques tests!

disons que vous avez quelques appels d'api retrofit pour récupérer une liste d'objets qui doivent être mis dans un adaptateur pour un RecyclerView etc. Nous aimerions tester si l'adaptateur est rempli d'articles appropriés sur appel réussi. Pour ce faire, nous aurons besoin de changer votre interface Retrofit implémentation, que vous utilisez pour faire des appels avec un mock, et faire quelques fausses réponses en profitant de la classe Mockito ArgumentCaptor.

@Config(constants = BuildConfig.class, sdk = 21,
    manifest = "app/src/main/AndroidManifest.xml")
@RunWith(RobolectricGradleTestRunner.class)
public class RetrofitCallTest {

    private MainActivity mainActivity;

    @Mock
    private RetrofitApi mockRetrofitApiImpl;

    @Captor
    private ArgumentCaptor<Callback<List<YourObject>>> callbackArgumentCaptor;

    @Before
    public void setUp() {            
        MockitoAnnotations.initMocks(this);

        ActivityController<MainActivity> controller = Robolectric.buildActivity(MainActivity.class);
        mainActivity = controller.get();

        // Then we need to swap the retrofit api impl. with a mock one
        // I usually store my Retrofit api impl as a static singleton in class RestClient, hence:
        RestClient.setApi(mockRetrofitApiImpl);

        controller.create();
    }

    @Test
    public void shouldFillAdapter() throws Exception {
        Mockito.verify(mockRetrofitApiImpl)
            .getYourObject(callbackArgumentCaptor.capture());

        int objectsQuantity = 10;
        List<YourObject> list = new ArrayList<YourObject>();
        for(int i = 0; i < objectsQuantity; ++i) {
            list.add(new YourObject());
        }

        callbackArgumentCaptor.getValue().success(list, null);

        YourAdapter yourAdapter = mainActivity.getAdapter(); // Obtain adapter
        // Simple test check if adapter has as many items as put into response
        assertThat(yourAdapter.getItemCount(), equalTo(objectsQuantity));
    }
}

procéder à l'essai en cliquant avec le bouton droit de la souris sur la classe d'essai et en tapant run.

Et c'est tout. Je suggère fortement D'utiliser Robolectric (avec Robolectric gradle plugin) et Mockito, ces libs rendent le test des applications android tout lotta plus facile. J'ai appris cette méthode de la suivante post de blog . Aussi, se référer à cette réponse .

mise à jour : si vous utilisez la modernisation avec RxJava, Vérifiez mon autre réponse sur ce aussi.

19
répondu maciekjanusz 2018-04-05 10:14:24

si vous utilisez .exécute () au lieu de .enqueue () il fait synchroniser l'exécution, donc les tests peuvent fonctionner correctement sans avoir besoin d'importer 3 bibliothèques différentes et d'ajouter du code ou de modifier les variantes de construction.

Comme:

public class LoginAPITest {

    @Test
    public void login_Success() {

        APIEndpoints apiEndpoints = RetrofitHelper.getTesterInstance().create(APIEndpoints.class);

        Call<AuthResponse> call = apiEndpoints.postLogin();

        try {
            //Magic is here at .execute() instead of .enqueue()
            Response<AuthResponse> response = call.execute();
            AuthResponse authResponse = response.body();

            assertTrue(response.isSuccessful() && authResponse.getBearer().startsWith("TestBearer"));

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}
11
répondu Adam Varhegyi 2017-02-24 17:17:00