1. Información general
En este tutorial, ilustraremos cómo aprovechar al máximo los espías en Mockito .
Hablaremos sobre la anotación @Spy , cómo apuntar a un espía y, finalmente, veremos la diferencia entre Mock y Spy .
Y por supuesto, para más bondad de Mockito, echa un vistazo a la serie aquí.
2. Ejemplo de espía simple
Comencemos con un ejemplo simple de cómo usar un espía .
En pocas palabras, la API es Mockito.spy () : para espiar un objeto real .
Esto nos permitirá llamar a todos los métodos normales del objeto mientras seguimos rastreando cada interacción, tal como lo haríamos con una simulación.
Bien, hagamos un ejemplo rápido en el que espiaremos un objeto ArrayList existente :
@Test public void whenSpyingOnList_thenCorrect() { List list = new ArrayList(); List spyList = Mockito.spy(list); spyList.add("one"); spyList.add("two"); Mockito.verify(spyList).add("one"); Mockito.verify(spyList).add("two"); assertEquals(2, spyList.size()); }
Observe cómo se llama realmente al método real add () y cómo el tamaño de spyList se convierte en 2.
3. La anotación @Spy
A continuación, veamos cómo usar la anotación @Spy . Podemos usar la anotación @Spy en lugar de spy () como en el siguiente ejemplo:
@Spy List spyList = new ArrayList(); @Test public void whenUsingTheSpyAnnotation_thenObjectIsSpied() { spyList.add("one"); spyList.add("two"); Mockito.verify(spyList).add("one"); Mockito.verify(spyList).add("two"); assertEquals(2, spyList.size()); }
Para habilitar la anotación de Mockito (como @Spy , @Mock ,…), debemos realizar una de las siguientes acciones :
- Llame al método MockitoAnnotations.initMocks (this) para inicializar campos anotados
- Utilice el corredor incorporado @RunWith (MockitoJUnitRunner.class)
4. Aporrear a un espía
Ahora, veamos cómo atrapar a un espía . Podemos configurar / anular el comportamiento de un método usando la misma sintaxis que usaríamos con un simulacro.
En el siguiente ejemplo, usamos doReturn () para anular el método size () :
@Test public void whenStubASpy_thenStubbed() { List list = new ArrayList(); List spyList = Mockito.spy(list); assertEquals(0, spyList.size()); Mockito.doReturn(100).when(spyList).size(); assertEquals(100, spyList.size()); }
5. Mock vs. Spy en Mockito
Ahora, analicemos la diferencia entre Mock y Spy en Mockito, no las diferencias teóricas entre los dos conceptos, solo cómo se diferencian dentro de Mockito.
Cuando Mockito crea un simulacro, lo hace desde la Clase de un tipo, no desde una instancia real. El simulacro simplemente crea una instancia de shell básica de la Clase, completamente instrumentada para rastrear las interacciones con ella.
Por otro lado, el espía envolverá una instancia existente . Seguirá comportándose de la misma manera que la instancia normal; la única diferencia es que también estará instrumentada para rastrear todas las interacciones con ella.
En el siguiente ejemplo, creamos una simulación de la clase ArrayList :
@Test public void whenCreateMock_thenCreated() { List mockedList = Mockito.mock(ArrayList.class); mockedList.add("one"); Mockito.verify(mockedList).add("one"); assertEquals(0, mockedList.size()); }
Como podemos ver, agregar un elemento a la lista simulada no agrega nada en realidad, simplemente llama al método sin otros efectos secundarios.
Un espía en el otro lado se comportará de forma diferente - lo que realmente va a llamar a la implementación real del complemento método y añadir el elemento a la lista subyacente:
@Test public void whenCreateSpy_thenCreate() { List spyList = Mockito.spy(new ArrayList()); spyList.add("one"); Mockito.verify(spyList).add("one"); assertEquals(1, spyList.size()); }
6. Comprensión de la excepción Mockito NotAMockException
En esta sección final, aprenderemos sobre Mockito NotAMockException . Esta excepción es una de las excepciones comunes que probablemente encontraremos cuando hagamos un mal uso de simulacros o espías .
Comencemos por ver bajo qué circunstancias puede ocurrir esta excepción:
List list = new ArrayList(); Mockito.doReturn(100).when(list).size(); assertEquals("Size should be 100: ", 100, list.size());
Cuando ejecutamos este fragmento de código, obtendremos el siguiente error:
org.mockito.exceptions.misusing.NotAMockException: Argument passed to when() is not a mock! Example of correct stubbing: doThrow(new RuntimeException()).when(mock).someMethod();
Afortunadamente, en el mensaje de error de Mockito queda bastante claro cuál es el problema aquí. En nuestro ejemplo, el objeto de lista no es un simulacro. El método Mockito when () espera un objeto simulado o espía como argumento .
Como también podemos ver, el mensaje de excepción incluso describe cómo debería ser una invocación correcta. Ahora que entendemos mejor cuál es el problema, solucionémoslo siguiendo la recomendación:
final List spyList = Mockito.spy(new ArrayList()); Mockito.doReturn(100).when(spyList).size(); assertEquals("Size should be 100: ", 100, spyList.size());
Nuestro ejemplo ahora se comporta como se esperaba y ya no vemos la excepción Mockito NotAMockException.
7. Conclusión
En este artículo rápido, discutimos los ejemplos más útiles del uso de espías de Mockito.
Aprendimos cómo crear un espía , cómo usar la anotación @Spy , cómo bloquear a un espía y, finalmente, la diferencia entre Mock y Spy .
La implementación de todos estos ejemplos se puede encontrar en GitHub .
Este es un proyecto de Maven, por lo que debería ser fácil de importar y ejecutar tal como está.
Y por supuesto, para más bondad de Mockito, echa un vistazo a la serie aquí.