Prueba de unidad de Android con Retrofit2 y Mockito o Robolectric

¿Puedo probar la respuesta real de retrofit2beta4? ¿Necesito Mockito o Robolectic?

No tengo actividades en mi proyecto, será una biblioteca y necesito probar que el servidor responda correctamente. Ahora tengo tal código y pegado …

@Mock ApiManager apiManager; @Captor private ArgumentCaptor<ApiCallback<Void>> cb; @Before public void setUp() throws Exception { apiManager = ApiManager.getInstance(); MockitoAnnotations.initMocks(this); } @Test public void test_login() { Mockito.verify(apiManager) .loginUser(Mockito.eq(login), Mockito.eq(pass), cb.capture()); // cb.getValue(); // assertEquals(cb.getValue().isError(), false); } 

Puedo hacer la respuesta falsa, pero necesito probar real. ¿Es el éxito? ¿Es correcto el cuerpo? ¿Me puede ayudar con el código?

Generalmente no es una buena idea probar solicitudes de servidor real. Vea esta entrada del blog para una interesante discusión sobre el tema. Según el autor, el uso de su servidor real es un problema porque:

  • Otra pieza en movimiento que puede intermitentemente fallar
  • Requiere alguna experiencia fuera del dominio de Android para implementar el servidor y mantenerlo actualizado
  • Difícil de activar casos de error / arista
  • Ejecución lenta de la prueba (aún haciendo llamadas HTTP)

Puede evitar todos los problemas anteriores mediante el uso de un servidor simulador como el MockWebServer de OkHttp para simular resultados de respuesta reales. Por ejemplo:

 @Test public void test() throws IOException { MockWebServer mockWebServer = new MockWebServer(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(mockWebServer.url("").toString()) //TODO Add your Retrofit parameters here .build(); //Set a response for retrofit to handle. You can copy a sample //response from your server to simulate a correct result or an error. //MockResponse can also be customized with different parameters //to match your test needs mockWebServer.enqueue(new MockResponse().setBody("your json body")); YourRetrofitService service = retrofit.create(YourRetrofitService.class); //With your service created you can now call its method that should //consume the MockResponse above. You can then use the desired //assertion to check if the result is as expected. For example: Call<YourObject> call = service.getYourObject(); assertTrue(call.execute() != null); //Finish web server mockWebServer.shutdown(); } 

Si necesita simular retrasos en la red, puede personalizar su respuesta de la siguiente manera:

 MockResponse response = new MockResponse() .addHeader("Content-Type", "application/json; charset=utf-8") .addHeader("Cache-Control", "no-cache") .setBody("{}"); response.throttleBody(1024, 1, TimeUnit.SECONDS); 

Como alternativa, puede utilizar MockRetrofit y NetworkBehavior para simular las respuestas de la API. Vea aquí un ejemplo de cómo usarlo.

Por último, si sólo desea probar su Servicio de Retrofit, lo más fácil sería crear una versión simulada de la misma que emita resultados falsos para sus pruebas. Por ejemplo, si tiene la siguiente interfaz de servicio GitHub :

 public interface GitHub { @GET("/repos/{owner}/{repo}/contributors") Call<List<Contributor>> contributors( @Path("owner") String owner, @Path("repo") String repo); } 

A continuación, puede crear el siguiente MockGitHub para sus pruebas:

 public class MockGitHub implements GitHub { private final BehaviorDelegate<GitHub> delegate; private final Map<String, Map<String, List<Contributor>>> ownerRepoContributors; public MockGitHub(BehaviorDelegate<GitHub> delegate) { this.delegate = delegate; ownerRepoContributors = new LinkedHashMap<>(); // Seed some mock data. addContributor("square", "retrofit", "John Doe", 12); addContributor("square", "retrofit", "Bob Smith", 2); addContributor("square", "retrofit", "Big Bird", 40); addContributor("square", "picasso", "Proposition Joe", 39); addContributor("square", "picasso", "Keiser Soze", 152); } @Override public Call<List<Contributor>> contributors(String owner, String repo) { List<Contributor> response = Collections.emptyList(); Map<String, List<Contributor>> repoContributors = ownerRepoContributors.get(owner); if (repoContributors != null) { List<Contributor> contributors = repoContributors.get(repo); if (contributors != null) { response = contributors; } } return delegate.returningResponse(response).contributors(owner, repo); } } 

A continuación, puede utilizar el MockGitHub en sus pruebas para simular el tipo de respuestas que está buscando. Para ver el ejemplo completo, vea las implementaciones de SimpleService y SimpleMockService para este ejemplo de Retrofit .

Habiendo dicho todo esto, si es absolutamente necesario conectarse al servidor real, puede configurar Retrofit para trabajar de forma síncrona con un ImmediateExecutor personalizado:

 public class ImmediateExecutor implements Executor { @Override public void execute(Runnable command) { command.run(); } } 

A continuación, aplíquelo al OkHttpClient que utilice al construir el Retrofit:

 OkHttpClient client = OkHttpClient.Builder() .dispatcher(new Dispatcher(new ImmediateExecutor())) .build(); Retrofit retrofit = new Retrofit.Builder() .client(client) //Your params .build(); 

La respuesta es demasiado fácil de lo que esperaba:

Utilizar CountDownLatch hace que su prueba espere hasta que llame countDown ()

 public class SimpleRetrofitTest { private static final String login = "your@login"; private static final String pass = "pass"; private final CountDownLatch latch = new CountDownLatch(1); private ApiManager apiManager; private OAuthToken oAuthToken; @Before public void beforeTest() { apiManager = ApiManager.getInstance(); } @Test public void test_login() throws InterruptedException { Assert.assertNotNull(apiManager); apiManager.loginUser(login, pass, new ApiCallback<OAuthToken>() { @Override public void onSuccess(OAuthToken token) { oAuthToken = token; latch.countDown(); } @Override public void onFailure(@ResultCode.Code int errorCode, String errorMessage) { latch.countDown(); } }); latch.await(); Assert.assertNotNull(oAuthToken); } @After public void afterTest() { oAuthToken = null; }} 

A menos que esté probando API de servidor de QA, es una mala idea por varias razones.

  • En primer lugar, se está poblando su base de datos de producción con datos incorrectos / falsos
  • Uso de los recursos del servidor, cuando pueden usarse mejor para servir solicitud válida

La mejor manera de usar Mockito, o Mock tus respuestas

Además, si debe probar su API de producción, pruebe una vez y agregue anotación @Ignore. De esa manera no se ejecutan todo el tiempo y no spam de su servidor con datos falsos y se puede utilizar siempre que se siente la api no se comporta correctamente.

  • Enviar Tecla Intro usando robotium para pruebas de Android?
  • Prueba unitaria de interfaz de usuario asíncrono con Espresso, IdlingResource falla con condición de carrera
  • Robolectric + OkHttp + retrofit + prueba de unidad rxJava
  • Cómo escribir la prueba de Robolectric (2.3) usando la base de datos
  • Automatización de la caja de prueba de la unidad Android: biblioteca Robolectric vs marco de pruebas de Android
  • Pruebas de escritura para aplicaciones Flow and Mortar
  • ¿Puedo usar Cobertura en pruebas de unidad con PowerMock?
  • Combine la cobertura jacoco de androidTest y pruebe
  • ¿Cómo obtengo un reporte de cobertura de jacoco usando el complemento Android gradle 0.10.0 o superior?
  • Cómo deshabilitar las pruebas de unidad de estudio de Android (androidTest)
  • ¿Cómo probar mejor el código Looper y Handler de la unidad en Android?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.