173 votes

Comment utiliser ArgumentCaptor pour le stubbing ?

Dans Mockito documentation y javadocs il dit

Il est recommandé d'utiliser ArgumentCaptor avec la vérification mais pas avec le stubbing.

mais je ne comprends pas comment ArgumentCaptor peut être utilisé pour le stubbing. Quelqu'un peut-il expliquer la déclaration ci-dessus et montrer comment ArgumentCaptor peut être utilisé pour le stubbing ou fournir un lien qui montre comment cela peut être fait ?

284voto

Rorick Points 3582

En supposant que la méthode suivante soit utilisée pour le test :

public boolean doSomething(SomeClass arg);

La documentation de Mockito indique que vous devez no utiliser le capteur de cette manière :

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);
assertThat(argumentCaptor.getValue(), equalTo(expected));

Parce que vous pouvez simplement utiliser le matcher pendant le stubbing :

when(someObject.doSomething(eq(expected))).thenReturn(true);

Mais la vérification est une autre histoire. Si votre test doit s'assurer que cette méthode a été appelée avec un argument spécifique, utilisez ArgumentCaptor et c'est le cas pour lequel il est conçu :

ArgumentCaptor<SomeClass> argumentCaptor = ArgumentCaptor.forClass(SomeClass.class);
verify(someObject).doSomething(argumentCaptor.capture());
assertThat(argumentCaptor.getValue(), equalTo(expected));

4voto

Aubergine Points 1197

Hypothétiquement, si la recherche vous a mené à cette question, alors vous voulez probablement ceci :

doReturn(someReturn).when(someObject).doSomething(argThat(argument -> argument.getName().equals("Bob")));

Pourquoi ? Parce que, comme moi, vous accordez de l'importance au temps et vous n'allez pas mettre en oeuvre .equals juste pour le bien du scénario de test unique.

Et 99 % des tests échouent avec un retour de nullité de Mock. Dans une conception raisonnable, vous éviterez le retour de nullité. null à tout prix, utiliser Optional ou passer à Kotlin. Cela implique que verify n'a pas besoin d'être utilisé si souvent et les ArgumentCaptors sont tout simplement trop fastidieux à écrire.

0voto

Stefan Mondelaers Points 191

La ligne

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);

ferait la même chose que

when(someObject.doSomething(Matchers.any())).thenReturn(true);

Ainsi, l'utilisation de argumentCaptor.capture() lors du stubbing n'a aucune valeur ajoutée. L'utilisation de Matchers.any() montre mieux ce qui se passe réellement et est donc meilleure pour la lisibilité. Avec argumentCaptor.capture(), vous ne pouvez pas lire les arguments qui sont réellement mis en correspondance. Et au lieu d'utiliser any(), vous pouvez utiliser des matchers plus spécifiques lorsque vous avez plus d'informations (classe de l'argument attendu), pour améliorer votre test.

Et un autre problème : Si l'on utilise argumentCaptor.capture() lors du stubbing, il devient difficile de savoir combien de valeurs on doit s'attendre à capturer après la vérification. Nous voulons capturer une valeur pendant la vérification, pas pendant le stubbing car à ce moment-là, il n'y a pas encore de valeur à capturer. Alors, qu'est-ce que la méthode de capture d'arguments capture pendant le stubbing ? Elle capture n'importe quoi car il n'y a rien à capturer pour le moment. Je considère que c'est un comportement indéfini et je ne veux pas utiliser un comportement indéfini.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X