Afin de corriger un bogue dans une application, j'ai modifié une méthode nommée postLogin
en ajoutant un appel à une méthode existante nommée getShoppingCart
.
Code
protected void postLogin() {
getShoppingCart();
}
Cependant, je ne sais pas quelle est la meilleure façon d'écrire un test unitaire postLogin
.
Approche 1
Utilisez la vérification de Mockito pour simplement vérifier que la méthode a été appelée.
verify(mock).getShoppingCart();
Approche 2
Testez l'effet secondaire de l'appel de méthode en récupérant la valeur du panier de l'utilisateur.
AssertNotNull(user.getShoppingCart());
Une approche est-elle meilleure que l'autre?
getShoppingCart()
méthode n'ait des effets secondaires, vous n'avez pas besoin de vérifier qu'elle s'appelle. S'il a des effets secondaires, vous devriez vraiment changer son nom car lesgetXXX()
méthodes devraient être idempotentes.getNextValue
? On pourrait dire que quelqu'un pourrait dire "Ne l'appelez pas un getter; changez le nom ennextValue
", mais j'ai déjà vugetNext
utilisé auparavant. Un meilleur exemple serait peut-être un objet représentant un électron; que se passe-t-il lorsque j'appellegetPosition
? Ou pire,getPosition(); getVelocity();
Réponses:
Je préfère généralement la méthode 2.
Pourquoi? Parce que vous voulez
postLogin
changer un état de votre système, mais comment il accomplit cela (et quelles méthodes il appelle en interne pour cela) n'est qu'un détail d'implémentation, rien sur quoi votre test unitaire ne devrait faire d'hypothèses. Il vaut donc mieux faire votre test en vérifiant simplement l'état final.la source
Je changerais getShoppingCart en quelque chose comme initializeShoppingCart, le but de la méthode devrait être clair pour quiconque la lit sans avoir besoin de vérifier ce que fait la méthode et des effets secondaires comme celui-ci peuvent provoquer un comportement surprenant pour les utilisateurs de la méthode.
Si getShoppingCart est dans une autre classe et qu'il est déjà testé unitaire, j'utiliserais l'approche 1 - pas besoin de tester à nouveau ce qui a déjà été testé. Dans ce cas, nous sommes sûrs que getShoppingCart fonctionne correctement et nous voulons seulement nous assurer qu'il est appelé à partir de postLogin, donc si quelqu'un à l'avenir supprime cet appel, le test échouera.
Si getShoppingCart est une méthode privée qui ne peut pas être testée par elle-même, j'utiliserais l'approche 2, pour m'assurer que lorsque postLogin est appelé, la fonctionnalité souhaitée de getShoppingCart est exécutée comme prévu.
la source
Lorsque vous testez un appel de fonction (vide ou non) qui a un effet secondaire, il est plus complet de tester que l'effet secondaire se produit non seulement, mais de vérifier que l'effet secondaire (sortie système ou changement d'état) est celui souhaité.
la source
Je ne discuterai pas de votre conception, mais dans votre cas, j'opterais pour la première approche car le test unitaire sert à tester quelles méthodes font techniquement quel que soit leur travail dans le domaine, c'est-à-dire ce que fait votre méthode
postLogin
? Techniquement, cela appellegetShoppingCard
donc vous devez tester qui appelle vraimentgetShoppingCard
, je créerais également un autre test pourgetShoppingCard
tester ce qu'il fait et s'il a des effets secondaires, je le vérifierai dans ce nouveau test.la source
Vous avez un bogue dans postLogin. La première chose à faire est donc de créer un test unitaire qui, lors de l'appel à postLogin sans l'ensemble d'informations attendu, "échouera".
De l'idée ci-dessus, une autre alternative parmi les 2 proposées est d'injecter les informations sur le panier en tant que paramètre. Si vous ne disposez pas des informations correctes, vous lancez une exception non vérifiée. Cela montrera clairement que sans les détails corrects, votre méthode est vouée à l'échec.
Cela nécessitera un petit changement où le client appelant le postLogin en ce moment doit également transmettre les informations du panier. Pour moi, c'est toujours cohérent maintenant que vous voyez qu'ils sont couplés. Ce couplage sera effectué par l'appelant.
Ensuite, vous n'auriez même pas besoin de tester getShoppingCart dans postLogin car la vraie méthode testée est postLogin. C'est celui qui a le bogue et le seul qui nécessite une correction et une validation appropriées. Avec la dépendance injectée, vous pourrez le tester facilement dans des conditions différentes et confirmer qu'aucune erreur n'est levée.
la source