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 …
- Ejecución de pruebas unitarias antes de cada construcción en Gradle
- Pruebas de unidades de Android fallan para tipo de compilación de depuración
- Cobertura de código con jacoco para una biblioteca de Android
- Prueba de unidades de Android con ContentProviders
- Prueba de la unidad de Android Studio SQLiteDataBase es nula
@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?
- Servicios Roboeléctricos y de Intención
- ActivityUnitTestCase arroja RuntimeException cuando se ejecuta con AndroidJUnitRunner
- `RenamingDelegatingContext` está obsoleto. ¿Cómo probamos SQLite db ahora?
- Archivo de cobertura de código Jacoco vacío que conduce a informes de cobertura falsa
- Sugar ORM necesita registros para ser guardado cada vez mientras que la prueba de unidad?
- ¿Cómo burlar el método antes de que se cree la actividad?
- Gradle - equivalente de test {} bloque de configuración para android
- Eliminación de contactos (crudos) en Android 2.x
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.
- No se encontró el comando adb
- ¿Cómo crear una barra de desplazamiento alfabética que muestra toda la letra en android?