Prueba de unidad de Android con Retrofit y Mockito

He separado los métodos de api retrofit de los métodos del código de actividad y quiero hacer una prueba de unidad en estos métodos, un ejemplo: La interfaz:

public interface LoginService { @GET("/auth") public void basicLogin(Callback<AuthObject> response); } 

Y este es el método que hacen la llamada, en la actividad principal me sale el objeto por el bus de eventos.

 public class AuthAPI { private Bus bus; LoginService loginService; public AuthAPI(String username, String password) { this.bus = BusProvider.getInstance().getBus(); loginService = ServiceGenerator.createService(LoginService.class, CommonUtils.BASE_URL, username, password); } public void Login() { loginService.basicLogin(new Callback<AuthObject>() { @Override public void success(AuthObject authObject, Response response) { bus.post(authObject); } @Override public void failure(RetrofitError error) { AuthObject authObject = new AuthObject(); authObject.setError(true); bus.post(authObject); } }); } } 

Y aquí la prueba

 @RunWith(MockitoJUnitRunner.class) public class AuthCallTest extends TestCase { AuthAPI authAPI; @Mock private LoginService mockApi; @Captor private ArgumentCaptor<Callback<AuthObject>> cb; @Before public void setUp() throws Exception { authAPI = new AuthAPI("username", "password"); MockitoAnnotations.initMocks(this); } @Test public void testLogin() throws Exception { Mockito.verify(mockApi).basicLogin((cb.capture())); AuthObject authObject = new AuthObject(); cb.getValue().success(authObject, null); assertEquals(authObject.isError(), false); } } 

Cuando inicio la prueba tengo este error

 Wanted but not invoked: mockApi.basicLogin(<Capturing argument>); -> at AuthCallTest.testLogin(AuthCallTest.java:42) Actually, there were zero interactions with this mock. 

Lo que hice mal, esto me está volviendo loco Traté de seguir esta guía sin éxito: http://www.mdswanson.com/blog/2013/12/16/reliable-android-http-testing-with-retrofit-and –mockito.html

Alguien ayúdeme 🙁

El artículo no es muy claro ya que echa de menos los pasos de configuración. Al visitar el proyecto GitHub enlazado en el artículo, puede ver el código fuente completo que explica los pasos que faltan:

1) Las muestras de código se extraen de una clase de prueba que prueba una actividad específica. Como parte de la configuración (es decir, en @Before ), reemplaza la referencia de la actividad a una implementación de la API de GitHub con una simulación. A continuación, llama a la actividad onCreate() .

2) Durante onCreate() , la actividad realiza una llamada a la API GitHub ahora reemplazada, pasando su objeto de Callback .

Estos dos primeros pasos explican por qué los Mockito.verify(mockApi).repositories(Mockito.anyString(), cb.capture()); Paso al comienzo de cada prueba funciona. Como la prueba se ejecuta después de @Before , el mockApi ha hecho una llamada en su método repositories() .

El resto del código es más fácil de entender una vez que está en su lugar. Como sólo ha creado un mockApi , pero no ha cambiado la Callback real que se utiliza, se cambia el contenido de la actividad. El resto del código verifica que esos cambios han tenido lugar, ya sea comprobando un ListView o el Toasts.


Así que para responder a su pregunta, usted necesita:

1) Al inicio del método de prueba, reemplace el objeto loginService de AuthAPI con su objeto mockApi y, a continuación, llame a AuthAPI.Login() .

2) Utilice verify() como ya está para comprobar que la función ha sido llamada.

3) Crear un AuthObject ejemplo y pasarlo a la función cb.getValue().success() .

4) Obtenga el AuthObject de su Bus y afirme que es el mismo que envió a la función callback.success() .

Esto prueba que AuthAPI.Login() envía correctamente a su Bus el AuthObject que recuperaría de Retrofit.


(Me doy cuenta de que la pregunta de SO fue escrita hace algún tiempo, pero como encontré el mismo artículo y tuve la misma confusión muy recientemente, pensé que esta respuesta podría ser útil para otros.)

El problema es que usted llama a verify en el momento equivocado: el propósito de verify es verificar que las interacciones con mockApi fueron lo que esperaba. Tan normalmente usted vería algo como:

 authApi.login(); Mockito.verify(mockApi).basicLogin((cb.capture())); 

Eso es también lo que el mensaje de error le está diciendo: verify basicLogin esperado para ser llamado, pero no lo fue.

He leído ese artículo también y sentí que faltaba algo. Todavía no entiendo la captura de argumentos. Así que no puedo ayudarte con eso 🙂

  • Cómo analizar la matriz JSON sin ningún objeto en Retrofit?
  • Excepción de interrupción de subproceso en modo Multi-ventana
  • Uso de Mockito con Retrofit 2.0
  • ¿Cuándo se debe usar RxJava Observable y cuándo Callback simple en Android?
  • ¿Es posible mostrar la barra de progreso cuando se descarga a través de Retrofit 2 Asynchronous?
  • Android: agregando imagen al tweet usando la API REST de tela, Twitter y Retrofit
  • Retrofit 2 - Parámetro de consulta de URL
  • Agregar cabecera a todas las solicitudes con Retrofit 2
  • Cómo POST JSON todo en bruto en el cuerpo de una solicitud de Retrofit?
  • No vuelva a ejecutar la llamada de Retrofit si todavía está en curso con RxJava 2
  • Publicar campos en este formato con Retrofit
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.