Quelle est la différence entre se moquer et espionner lors de l'utilisation de Mockito?
137
Quel serait un cas d'utilisation pour une utilisation d'un espion Mockito?
Il me semble que chaque cas d'utilisation d'espionnage peut être traité avec un simulacre, en utilisant callRealMethod.
Une différence que je peux voir est que si vous voulez que la plupart des appels de méthode soient réels, cela économise quelques lignes de code pour utiliser une simulation par rapport à un espion. Est-ce cela ou est-ce que je rate la vue d'ensemble?
Enfin, après de nombreux débats et discussions internes sur la liste de diffusion, un support partiel a été ajouté à Mockito. Auparavant, nous considérions les simulations partielles comme des odeurs de code. Cependant, nous avons trouvé un cas d'utilisation légitime pour les simulations partielles.
Avant la version 1.8, spy () ne produisait pas de véritables simulations partielles et c'était déroutant pour certains utilisateurs. En savoir plus sur l'espionnage: ici ou en javadoc pour la méthode spy (Object).
callRealMethod()a été introduit après spy(), mais spy () a été laissé là bien sûr, pour assurer la compatibilité descendante.
Sinon, vous avez raison: toutes les méthodes d'un espion sont réelles à moins d'être écrasées. Toutes les méthodes d'un simulacre sont stubbed sauf si callRealMethod()est appelé. En général, je préférerais utiliser callRealMethod(), car cela ne m'oblige pas à utiliser l' doXxx().when()idiome au lieu du traditionnelwhen().thenXxx()
Le problème de préférer le simulacre à l'espion dans ces cas, c'est quand la classe utilise un membre qui n'est pas injecté dedans (mais initialisé localement), et est plus tard utilisé par la méthode "réelle"; dans le simulacre, le membre sera initialisé à sa valeur Java par défaut, ce qui pourrait entraîner un comportement incorrect ou même une exception NullPointerException. La façon de réussir est d'ajouter une méthode "init" puis de l'appeler "vraiment", mais cela me semble un peu exagéré.
Eyal Roth
Extrait du document: "Les espions doivent être utilisés avec précaution et occasionnellement, par exemple lors de l'utilisation de code hérité." L'espace de test unitaire souffre de trop de façons de faire la même chose.
gdbj
89
Différence entre un espion et un simulacre
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:
Comme vous pouvez 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, par contre, se comportera différemment - il appellera en fait l'implémentation réelle de la méthode add et ajoutera l'élément à la liste sous-jacente:
Ici, nous pouvons sûrement dire que la vraie méthode interne de l'objet a été appelée car lorsque vous appelez la méthode size (), vous obtenez la taille 1, mais cette méthode size () n'est pas moquée! Alors d'où viens-je? La méthode interne real size () est appelée car size () n'est pas simulée (ou stubbed) et nous pouvons donc dire que l'entrée a été ajoutée à l'objet réel.
Dans le premier exemple, pourquoi mockedList.size()retourne-t-il 0si cette méthode n'a pas non plus été supprimée? Est-ce juste une valeur par défaut étant donné le type de retour de la méthode?
mike
@mike: mockedList.size()renvoie une intvaleur par défaut de int0 en Java. Si vous essayez d'exécuter assertEquals(0, mockedList.size());après mockedList.clear();, le résultat reste le même.
realPK
2
Cette réponse est bien et simplement écrite et m'a aidé à enfin comprendre la différence entre mock et espion. Joli.
PesaLe
38
S'il y a un objet avec 8 méthodes et que vous avez un test où vous voulez appeler 7 méthodes réelles et stub une méthode, vous avez deux options:
En utilisant un simulacre, vous devrez le configurer en appelant 7 callRealMethod et en stub une méthode
En utilisant un, spyvous devez le configurer en stubbing une méthode
La documentation officielle sur doCallRealMethodrecommande l'utilisation d'un espion pour les simulations partielles.
Voir aussi javadoc spy (Object) pour en savoir plus sur les simulations partielles. Mockito.spy () est une méthode recommandée pour créer des simulations partielles. La raison en est que cela garantit que les méthodes réelles sont appelées contre un objet correctement construit car vous êtes responsable de la construction de l'objet passé à la méthode spy ().
Oui, vous pouvez passer au premier code, mais l'API est ensuite modifiée. Si cette méthode est utilisée par de nombreux endroits, vous devez tous les changer.
L'alternative est que vous pouvez extraire la dépendance comme ceci:
Différence entre un espion et un simulacre
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:
Comme vous pouvez 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, par contre, se comportera différemment - il appellera en fait l'implémentation réelle de la méthode add et ajoutera l'élément à la liste sous-jacente:
Ici, nous pouvons sûrement dire que la vraie méthode interne de l'objet a été appelée car lorsque vous appelez la méthode size (), vous obtenez la taille 1, mais cette méthode size () n'est pas moquée! Alors d'où viens-je? La méthode interne real size () est appelée car size () n'est pas simulée (ou stubbed) et nous pouvons donc dire que l'entrée a été ajoutée à l'objet réel.
Source: http://www.baeldung.com/mockito-spy + notes personnelles.
la source
mockedList.size()
retourne-t-il0
si cette méthode n'a pas non plus été supprimée? Est-ce juste une valeur par défaut étant donné le type de retour de la méthode?mockedList.size()
renvoie uneint
valeur par défaut deint
0 en Java. Si vous essayez d'exécuterassertEquals(0, mockedList.size());
aprèsmockedList.clear();
, le résultat reste le même.S'il y a un objet avec 8 méthodes et que vous avez un test où vous voulez appeler 7 méthodes réelles et stub une méthode, vous avez deux options:
spy
vous devez le configurer en stubbing une méthodeLa documentation officielle sur
doCallRealMethod
recommande l'utilisation d'un espion pour les simulations partielles.la source
Spy peut être utile lorsque vous souhaitez créer des tests unitaires pour du code hérité .
J'ai créé un exemple exécutable ici https://www.surasint.com/mockito-with-spy/ , j'en copie une partie ici.
Si vous avez quelque chose comme ce code:
Vous n'avez peut-être pas besoin d'espionnage, car vous pouvez simplement vous moquer de DepositMoneyService et WithdrawMoneyService.
Mais avec du code hérité, la dépendance est dans le code comme ceci:
Oui, vous pouvez passer au premier code, mais l'API est ensuite modifiée. Si cette méthode est utilisée par de nombreux endroits, vous devez tous les changer.
L'alternative est que vous pouvez extraire la dépendance comme ceci:
Ensuite, vous pouvez utiliser l'espion pour injecter la dépendance comme ceci:
Plus de détails dans le lien ci-dessus.
la source
Mock
est un objet double nu. Cet objet a les mêmes signatures de méthodes mais la réalisation est vide et renvoie la valeur par défaut - 0 et nullSpy
est un double objet cloné. Le nouvel objet est cloné sur la base d'un objet réel mais vous avez la possibilité de vous en moquer[Tester les types doubles]
la source