Mockito - Utilisation d'espions

1. Vue d'ensemble

Dans ce didacticiel, nous allons illustrer comment tirer le meilleur parti des espions dans Mockito .

Nous parlerons de l' annotation @Spy , de la façon de stuber un espion et, enfin, nous entrerons dans la différence entre Mock et Spy .

Et bien sûr, pour plus de bonté Mockito, jetez un œil à la série ici.

2. Exemple d' espionnage simple

Commençons par un exemple simple d' utilisation d'un espion .

En termes simples, l'API est Mockito.spy () - pour espionner un objet réel .

Cela nous permettra d'appeler toutes les méthodes normales de l'objet tout en suivant chaque interaction, comme nous le ferions avec une simulation.

OK, faisons un exemple rapide où nous allons espionner un objet ArrayList existant :

@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()); }

Notez comment la méthode réelle add () est réellement appelée et comment la taille de spyList devient 2.

3. L' annotation @Spy

Ensuite, voyons comment utiliser l' annotation @Spy . Nous pouvons utiliser l' annotation @Spy au lieu de spy () comme dans l'exemple suivant:

@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()); }

Pour activer les annotations Mockito (telles que @Spy , @Mock ,…), nous devons effectuer l'une des opérations suivantes:

  • Appelez la méthode MockitoAnnotations.initMocks (this) pour initialiser les champs annotés
  • Utilisez le runner intégré @RunWith (MockitoJUnitRunner.class)

4. Écraser un espion

Maintenant - Voyons comment stuber un espion . Nous pouvons configurer / remplacer le comportement d'une méthode en utilisant la même syntaxe que nous utiliserions avec un simulacre.

Dans l'exemple suivant, nous utilisons doReturn () pour remplacer la méthode 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 dans Mockito

Maintenant - discutons de la différence entre Mock et Spy dans Mockito - pas les différences théoriques entre les deux concepts, juste comment ils diffèrent au sein même de Mockito.

Lorsque Mockito crée une maquette, il le fait à partir de la classe d'un type, et non d'une instance réelle. Le simulacre crée simplement une instance de shell simple de la classe, entièrement instrumentée pour suivre les interactions avec elle.

D'autre part, l'espion encapsulera une instance existante . Elle se comportera toujours de la même manière que l'instance normale - la seule différence est qu'elle sera également instrumentée pour suivre toutes les interactions avec elle.

Dans l'exemple suivant, nous créons une maquette de la classe ArrayList :

@Test public void whenCreateMock_thenCreated() { List mockedList = Mockito.mock(ArrayList.class); mockedList.add("one"); Mockito.verify(mockedList).add("one"); assertEquals(0, mockedList.size()); }

Comme nous pouvons le voir - l'ajout d'un élément dans la liste simulée n'ajoute en fait rien - il appelle simplement la méthode sans autre effet secondaire.

Un espion d'autre part se comportera différemment - il fait appel à la mise en œuvre réelle de l' ajouter méthode et ajouter l'élément à la liste sous - jacente:

@Test public void whenCreateSpy_thenCreate() { List spyList = Mockito.spy(new ArrayList()); spyList.add("one"); Mockito.verify(spyList).add("one"); assertEquals(1, spyList.size()); }

6. Comprendre l'exception Mockito NotAMockException

Dans cette dernière section, nous en apprendrons davantage sur l'exception Mockito NotAMockException . Cette exception est l'une des exceptions courantes que nous rencontrerons probablement lors de l'utilisation abusive de moqueries ou d'espions .

Commençons par voir dans quelles circonstances cette exception peut se produire:

List list = new ArrayList(); Mockito.doReturn(100).when(list).size(); assertEquals("Size should be 100: ", 100, list.size()); 

Lorsque nous exécutons cet extrait de code, nous obtenons l'erreur suivante:

org.mockito.exceptions.misusing.NotAMockException: Argument passed to when() is not a mock! Example of correct stubbing: doThrow(new RuntimeException()).when(mock).someMethod(); 

Heureusement, le message d'erreur Mockito montre clairement quel est le problème ici. Dans notre exemple, l' objet de liste n'est pas une simulation. La méthode Mockito when () attend un objet simulé ou espion comme argument .

Comme nous pouvons également le voir, le message Exception décrit même à quoi devrait ressembler un appel correct. Maintenant que nous avons une meilleure compréhension de ce qu'est le problème, corrigeons-le en suivant la recommandation:

final List spyList = Mockito.spy(new ArrayList()); Mockito.doReturn(100).when(spyList).size(); assertEquals("Size should be 100: ", 100, spyList.size()); 

Notre exemple se comporte désormais comme prévu et nous ne voyons plus l'exception Mockito NotAMockException.

7. Conclusion

Dans cet article rapide, nous avons discuté des exemples les plus utiles d'utilisation d'espions Mockito.

Nous avons appris à créer un espion , à utiliser l' annotation @Spy , à stuber un espion et, enfin, à faire la différence entre Mock et Spy .

L'implémentation de tous ces exemples se trouve à l'adresse over sur GitHub .

Il s'agit d'un projet Maven, il devrait donc être facile à importer et à exécuter tel quel.

Et bien sûr, pour plus de bonté Mockito, jetez un œil à la série ici.