Comment puis-je empêcher mes tests unitaires d'exiger des connaissances sur la mise en œuvre internes lors de l'utilisation d'objets fantaisie?

StackOverflow https://stackoverflow.com/questions/3448121

Question

Je suis toujours dans les étapes d'apprentissage concernant les tests unitaires et en particulier en ce qui concerne moqueuse (j'utilise le PascalMock et DUnit cadres). Une chose que je maintenant trébuché sur était que je ne pouvais pas trouver un moyen de contourner les détails de mise en œuvre difficile codantes de la classe testé / interface dans mon test unitaire et que tout se sent mal ...

Par exemple: Je veux tester une classe qui implémente une interface très simple pour lire et écrire les paramètres d'application (nom essentiellement / paires de valeurs). L'interface qui est présentée au consommateur est complètement agnostique où et comment les valeurs sont effectivement stockées (par exemple registre, fichier INI, XML, base de données, etc.). Bien entendu, la couche d'accès est mis en œuvre par encore une autre classe qui obtient injecté dans la classe testée sur la construction. J'ai créé un objet fantaisie pour cette couche d'accès et je suis maintenant en mesure de tester pleinement la classe implémentant l'interface sans lire ou d'écrire quoi que ce soit en fait à un registre / fichier INI / whatever.

Toutefois, afin d'assurer la se comporte simulacres exactement comme la vraie chose quand on y accède par la classe testée, mes tests unitaires doivent mettre en place l'objet maquette en définissant très explicitement les appels de méthode attendus et les valeurs de rendement attendu par la classe testée . Cela signifie que si jamais je dois apporter des modifications à l'interface de la couche d'accès ou à la façon dont les utilisations de la classe testé cette couche je vais aussi changer les tests unitaires pour la classe qui utilise en interne cette interface, même si le < strong> Interface de la classe, je suis en fait l'essai n'a pas changé du tout. Est-ce quelque chose que je vais devoir vivre avec ou lors de l'utilisation des simulacres est-il une meilleure façon de concevoir les dépendances de classe qui éviterait cela?

Était-ce utile?

La solution

  

Est-ce quelque chose que je vais devoir   vivre lors de l'utilisation se moque ou est-il   une meilleure façon de concevoir la   classe dépendances qui éviteraient   cela?

Beaucoup de fois se moque (cadres particulièrement sensibles comme JMock) vous forcer à expliquer les détails qui ne sont pas directement liés au comportement que vous essayez de tester, et parfois cela peut même être utile en exposant le code suspect qui est faire trop et a trop d'appels / dépendances.

Cependant, dans votre cas, si je lis bien votre description, il semble que vous n'avez pas vraiment un problème. Si vous concevez la lecture / écriture couche correctement et avec un niveau d'abstraction approprié, vous ne devriez pas avoir à le changer.

  

Cela signifie que si je ne devrait jamais avoir   apporter des modifications à l'interface   la couche d'accès ou à la façon dont   la classe testée utilise cette couche I   devra également changer l'unité   Les tests de la classe interne   utilisations interface même si la   l'interface de la classe, je suis en fait   test n'a pas changé du tout.

est-ce pas le point d'écrire la couche d'accès Abstraite pour éviter cela? En général, suite à la Ouvrir / principe fermé , une interface de ce type ne doit pas changement et ne doit pas rompre le contrat avec la classe qui le consume, et par extension, il ne se cassera pas non plus vos tests unitaires. Maintenant, si vous changez l'ordre des appels de méthode, ou doivent faire de nouveaux appels à la couche abstraite, alors, oui, en particulier avec certains cadres, vos attentes Mock briser. Cela fait partie seulement du coût d'utilisation se moque, et il est tout à fait acceptable. Mais l'interface elle-même doit, en général, restent stables.

Autres conseils

  

pour que les se comporte simulacres exactement comme la vraie chose quand on y accède par la classe testée, mes tests unitaires doivent mettre en place l'objet maquette en définissant très explicitement les appels de méthode attendus et les valeurs de rendement attendu par la classe testée.

Correct.

  

passe à l'interface de la couche d'accès ou à la façon dont les utilisations de la classe testé cette couche je vais aussi changer les tests unitaires

Correct.

  

même si l'interface de la classe, je suis en fait l'essai n'a pas changé du tout.

"En fait le test"? Vous voulez dire que la classe d'interface exposée? C'est très bien.

La façon dont la classe « testé » (interface) utilise les moyens de la couche d'accès vous avez modifié l'interface interne à la couche d'accès. changements d'interface (même les internes) nécessitent des changements de test et peuvent conduire à la rupture si vous avez fait quelque chose de mal.

Rien de mal à cela. En effet, le fait est que toute modification de la couche d'accès doit nécessitent des modifications aux simulacres pour assurer que le changement « fonctionne ».

Le test est pas censé être « robuste ». Il est censé être fragile. Si vous faites un changement qui modifie le comportement interne, alors les choses peut pause. Si vos tests étaient trop robustes qu'ils ne le feraient pas quelque chose de test - ils travailleraient tout simplement. Et ce qui ne va pas.

Les tests ne doivent travailler pour la raison exacte droit.

Il suffit de mettre quelques noms à votre exemple,

  • met en œuvre RegistryBasedDictionary le rôle (interface) Dictionnaire.
  • RegistryBasedDictionary a une dépendance sur le rôle RegistryAccessor, mis en œuvre par RegistryWinAPIWrapper.

Vous êtes actuellement intéressés à tester RegistryBasedDictionary. Les tests unitaires injectent une dépendance simulée pour le rôle RegistryAccessor et vérifieraient l'interaction attendue avec les dépendances.

scroll top