Quand utiliser Mockito.vérifier()?
- Je écrire des cas de test jUnit pour 3 raisons:
- À ce que mon code répond à toutes les fonctionnalités requises, en vertu de tous (ou la plupart) des combinaisons en entrée/valeurs.
- Pour s'assurer que je peux changer la mise en œuvre, et de s'appuyer sur des cas de test JUnit pour me dire que tous mes fonctionnalité est toujours satisfait.
- Une documentation de tous les cas d'utilisation de mon code de poignées, et d'agir comme une spécification pour la refactorisation du code jamais besoin d'être réécrite. (Refactoriser le code, et si mon jUnit tests échouent - vous avez sans doute raté quelques cas d'utilisation).
Je ne comprends pas pourquoi ou quand Mockito.verify()
doit être utilisé. Quand je vois verify()
appelle, il me dit que mon jUnit est de plus en plus conscients de la mise en œuvre. (Et donc de changer ma mise en œuvre de casser mon jUnits, même si mon la fonctionnalité n'a pas été affectée).
Je suis à la recherche de:
-
De ce que devraient être les lignes directrices sur l'utilisation appropriée des
Mockito.verify()
? -
Est-il fondamentalement correcte pour jUnits d'être conscient de, ou étroitement associés à la mise en œuvre de la classe sous test?
- J'essaie de rester loin de l'aide de vérifier() autant que je peux, pour la même raison, vous exposé (je ne veux pas que mon test de l'unité à prendre conscience de la mise en œuvre), mais il est un cas quand je n'ai pas le choix - écrasa vide-méthodes. Généralement parlant comme ils le font pas de retour à ce qu'ils ne contribuent pas à votre "réel" de sortie; mais encore, vous devez savoir qu'il a été appelé. Mais je suis d'accord avec vous, il n'a pas de sens d'utiliser de vérifier pour vérifier le flux d'exécution.
Vous devez vous connecter pour publier un commentaire.
Si le contrat de la classe A comprend le fait qu'il appelle la méthode B d'un objet de type C, alors vous devriez le tester en faisant un simulacre de type C, et de vérifier que la méthode B a été appelé.
Cela implique que le contrat de la classe A a assez de détails pour qu'on parle de type C (qui peut être une interface ou une classe). Donc, oui, nous parlons d'un niveau de précision qui va au-delà de la simple "configuration système requise", et va d'une certaine manière à la description de la mise en œuvre.
Ce qui est normal pour les tests unitaires. Lorsque vous êtes de tests unitaires, vous voulez vous assurer que chaque unité est en train de faire la "bonne chose", et qui comprend généralement ses interactions avec les autres unités. "Unités" ici pourrait signifier les classes, ou les plus grands sous-ensembles de votre application.
Mise à jour:
J'ai l'impression que cela ne s'applique pas seulement à la vérification, mais à écrasant ainsi. Dès que vous vous cognez une méthode d'un collaborateur de la classe, de votre unité de test est devenu, en un certain sens, dépend de la mise en œuvre. C'est dans la nature des tests d'unité de l'être. Depuis Mockito est autant à propos de cogner comme il est à propos de la vérification, le fait que vous êtes à l'aide de Mockito à tous les implique que vous allez courir à travers ce genre de dépendance.
Dans mon expérience, si je change la mise en œuvre d'une classe, je dois souvent changer la mise en œuvre de ses tests unitaires de match. En général, cependant, je n'aurai pas à changer l'inventaire de ce que les tests unitaires, il y sont pour la classe; à moins, bien sûr, la raison de ce changement était l'existence d'un état que je n'ai pas pu tester plus tôt.
C'est ce que les tests unitaires sont sur. Un test qui ne souffre pas de ce genre de dépendance sur le chemin collaborateur de classes sont utilisées est vraiment un sous-système de test ou un test d'intégration. Bien sûr, ce sont souvent écrits avec JUnit trop, et impliquent souvent l'utilisation de moqueries. À mon avis, "JUnit" est un nom terrible, pour un produit qui nous permet de produire tous les différents types de test.
equals()
ouequalsIgnoreCase()
n'aurait jamais être quelque chose qui a été spécifié dans les exigences d'une classe, pour ne jamais avoir un test d'unité en soi. Cependant, "fermeture de la connexion DB lorsque tout est terminé" (quoi que cela signifie en termes de mise en œuvre) pourrait bien être une condition de la classe, même si ce n'est pas une "exigence de l'entreprise". Pour moi, cela revient à la relation entre le contrat ...m1
vraiment doit appelerm2
? Ou est-il nécessaire de faire quelque chose qui se trouve être identique à ce que l'm2
n'? Ce dernier semble beaucoup plus probable pour moi - et si c'est le cas, il vous suffit de test quim1
fait la bonne chose, non pas qu'il appellem2
.David réponse est, bien sûr, correct mais n'est pas tout à fait expliquer pourquoi vous voulez cette.
Fondamentalement, lorsque les tests unitaires vous testez une unité de fonctionnalité dans l'isolement. Vous testez si l'entrée produit de la sortie attendue. Parfois, vous avez à tester des effets secondaires ainsi. En un mot, vérifiez vous permet de le faire.
Par exemple, vous avez peu de logique d'entreprise qui est censé stocker des choses à l'aide d'un DAO. Vous pouvez faire cela à l'aide d'un test d'intégration qui instancie le DAO, crochets à la logique métier et puis piqûres autour de la base de données pour voir si la durée de trucs a obtenu stockées. Ce n'est pas une unité de test plus.
Ou on pourrait se moquer de la DAO et de vérifier qu'elle est appelée dans la façon dont vous vous attendez. Avec mockito vous pouvez vérifier que quelque chose est appelé, comment souvent, il est appelé, et même d'utiliser les allumettes sur les paramètres pour s'assurer qu'elle est appelée, dans un sens particulier.
Le revers de la médaille de l'unité de test de ce genre est, en effet, que vous liant les tests à la mise en œuvre qui fait de refactoring un peu plus difficile. D'autre part, une bonne conception de l'odorat est la quantité de code qu'il faut pour l'exercer correctement. Si vos tests doivent être très long, probablement quelque chose de mal avec la conception. Donc le code avec un lot d'effets secondaires/interactions complexes qui doivent être testés n'est probablement pas une bonne chose.
C'est une grande question!
Je pense que la cause de cela est la suivante, nous sommes en utilisant JUnit, non seulement pour les tests unitaires. Donc la question qui devrait être divisée en place:
donc, si nous ferons abstraction plus élevé que les tests unitaires, la question peut être reformulée "à l'Aide de blanc-boîte de de tests unitaires avec Mockito.vérifier() crée un grand couple entre l'unité de test et de mon pourrait la mise en œuvre, peut-on faire une "gris-box" de tests unitaires et quelles sont les règles du pouce que je devrais utiliser pour cette".
Maintenant, nous allons aller à travers l'ensemble de cette étape-par-étape.
*- Dois-je utiliser Mockito.vérifier() dans mon intégration (ou tout autre plus-que-tests unitaires) les tests?*
Je pense que la réponse est clairement non, d'ailleurs vous ne devriez pas utiliser se moque de cela. Votre test doit être aussi réel que possible. Vous test complet de cas d'utilisation, n'est pas isolée de la partie de l'application.
*boîte noire vs blanc-boîte de de tests unitaires*
Si vous utilisez boîte noire approche qu'est-ce que vous avez vraiment, vous offre (toutes classes d'équivalence) entrée, un état, et les tests que vous recevrez les résultats attendus. Dans cette approche à l'aide d'objets fantaisie, en général, est la justifie (vous venez d'imiter ce qu'ils font la bonne chose; vous ne voulez pas tester), mais en l'appelant Mockito.vérifier() est superflu.
Si vous utilisez blanc-boîte de approche qu'est-ce que vous avez vraiment, vous testez la comportement de votre unité. Dans cette approche, l'appeler, à Mockito.vérifier() est essentielle, vous devez vérifier que votre appareil se comporte comme vous vous attendez à.
règles du pouce pour le gris-zone-test
Le problème avec la boîte blanche de test est-il crée un haut de couplage. Une solution possible est de faire des gris-zone-test, pas de blanc-zone-test. C'est une sorte de combinaison de noir&blanc de la boîte de test. Vous êtes vraiment tester les comportement de votre unité comme dans blanche-boîte de test, mais en général vous rendre la mise en œuvre-agnostique lorsque cela est possible. Lorsque c'est possible, il vous suffira de faire un chèque comme dans le noir-boîte de cas, il affirme que la production est ce qui est prévu pour être. Donc, l'essence de votre question est de savoir quand il est possible.
C'est vraiment dur. Je n'ai pas un bon exemple, mais je peux vous donner des exemples. Dans le cas qui a été mentionné ci-dessus avec equals() vs equalsIgnoreCase (), vous ne devez pas appeler Mockito.vérifier(), il suffit de faire valoir la sortie. Si vous ne pouvais pas le faire, briser votre code à l'unité plus petite, jusqu'à ce que vous pouvez faire. D'autre part, supposons que vous avez des @Service et vous êtes d'écrire @Web-Service qui est essentiellement wrapper sur votre @Service - il des délégués de tous les appels à la @Service (et faire un peu d'erreur de manipulation). Dans ce cas, l'appel à Mockito.vérifier() est essentielle, vous ne devriez pas dupliquer tous vos contrôles que vous avez fait pour la @Serive, en vérifiant que vous êtes d'appel de @Service avec un bon parammeter liste est suffisante.
Je dois dire, que vous avez absolument raison, à partir d'une approche classique du point de vue:
Il est important de se rappeler qu'il n'existe pas d'outils universels. Le type de logiciel, il est de taille, les objectifs de l'entreprise et de la situation du marché, de compétences de l'équipe et de nombreux autres facteurs influent sur la décision sur l'approche à utiliser à votre cas particulier.
Comme l'ont dit certains
Au sujet de votre préoccupation au sujet de la rupture de vos tests lors d'un refactoring, c'est un peu attendu lors de l'utilisation de mocks/talons/espions. Je veux dire que, par définition, et non en ce qui concerne une mise en œuvre spécifique comme Mockito.
Mais vous pourriez penser de cette façon - si vous avez besoin de faire un refactoring qui permettrait de créer des changements majeurs dans la façon dont votre méthode fonctionne, c'est une bonne idée de le faire sur une approche TDD, ce qui signifie que vous pouvez changer votre test première pour définir le nouveau comportement (qui échouent le test), et puis faire les changements et obtenir le test réussi de nouveau.
Dans la plupart des cas, quand les gens n'aiment pas l'aide de Mockito.vérifier, c'est parce qu'il est utilisé pour vérifier tout ce que l'testé l'unité est en train de faire et cela signifie que vous devrez adapter votre test si rien ne change en elle.
Mais, je ne pense pas que c'est un problème. Si vous voulez être en mesure de changer ce qu'une méthode ne sans la nécessité de changer son test, que, fondamentalement signifie que vous voulez écrire des tests qui ne sont pas tout tester votre méthode est en train de faire, parce que vous n'avez pas envie de tester vos modifications. Et c'est la mauvaise façon de penser.
Ce qui est vraiment un problème, c'est que si vous pouvez modifier ce que votre méthode ne et un test unitaire qui est censé couvrir les fonctionnalités entièrement ne pas échouer. Cela signifie que quelle que soit l'intention de votre changement est le résultat de votre changement n'est pas couvert par le test.
À cause de cela, je préfère de se moquer autant que possible: aussi se moquer de vos objets de données. Lorsque vous faites ce que vous pouvez non seulement utiliser de vérifier pour vérifier que les bonnes méthodes des autres classes sont appelés, mais également que la transmission des données recueillies par l'intermédiaire des méthodes correctes de ces objets de données. Et pour le rendre complet, vous devez tester l'ordre dans lequel les appels se produire.
Exemple: si vous modifiez un db entité de l'objet et de l'enregistrer à l'aide d'un référentiel, il ne suffit pas de vérifier que les opérateurs de l'objet sont appelés avec les données correctes et que la méthode save du référentiel est appelé. Si elles sont appelées dans le mauvais ordre, votre méthode ne fonctionne toujours pas faire ce qu'il doit faire.
Donc, je n'utilise pas Mockito.vérifier, mais je afinde créer un objet avec tous les objets fantaisie et utiliser aussitôt.de vérifier la place. Et si vous voulez faire cela, vous devez également appeler Mockito.verifyNoMoreInteractions à la fin et de passer tous les simulacres. Sinon, quelqu'un peut ajouter de nouvelles fonctionnalités/comportement sans le tester, ce qui signifierait que, après tout vos statistiques de couverture de 100% et encore, vous sont empilage de code qui n'est pas affirmé ou vérifié.