unit tutorial test mock how calls android unit-testing mockito robolectric retrofit2

test - mockwebserver android tutorial



Prueba de unidad Android con Retrofit2 y Mockito o Robolectric (3)

En general, no es una buena idea probar las solicitudes reales del servidor. Vea esta publicación en el blog para una discusión interesante sobre el tema. Según el autor, usar tu servidor real es un problema porque:

  • Otra pieza en movimiento que puede fallar intermitentemente
  • Requiere cierta experiencia fuera del dominio de Android para implementar el servidor y mantenerlo actualizado
  • Difícil desencadenar errores / casos extremos
  • Ejecución de prueba lenta (sigue haciendo llamadas HTTP)

Puede evitar todos los problemas anteriores utilizando un servidor simulado como 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);

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

Finalmente, si solo quiere probar su Servicio de modificación, lo más fácil sería crear una versión simulada que emita resultados simulados 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); } }

Luego puede usar MockGitHub en sus pruebas para simular los tipos de respuestas que está buscando. Para ver el ejemplo completo, consulte las implementaciones de SimpleService y SimpleMockService para este ejemplo de Retrofit .

Habiendo dicho todo esto, si absolutamente debe conectarse al servidor real, puede configurar Retrofit para que funcione de forma sincronizada con un ImmediateExecutor personalizado:

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

Luego, aplíquelo al OkHttpClient que usa cuando construye la Retrofit:

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

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

No tengo actividades en mi proyecto, será una biblioteca y necesito probar si el servidor responde correctamente. Ahora tengo ese código y me he quedado atrapado ...

@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 una respuesta falsa, pero necesito una prueba real. ¿Es éxito? ¿Es su cuerpo correcto? ¿Me puedes ayudar con el código?


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

El uso de CountDownLatch hace que la prueba espere hasta que llame a 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 la API del servidor QA, es una mala idea por varias razones.

  • En primer lugar, está completando su base de datos de producción con datos incorrectos / falsos
  • Utilizando los recursos del servidor, cuando pueden utilizarse mejor para servir una solicitud válida

La mejor forma de usar Mockito, o burlarse de tus respuestas

Además, si debe probar su API de producción, pruébela una vez y agregue la anotación @Ignore. De esta manera, no se ejecutan todo el tiempo y no envían spam a su servidor con datos falsos y puede usarlo siempre que sienta que la API no se está comportando correctamente.