7

Considérons un débutant en charge de l'injection de dépendances. Nous analysons deux classes pertinentes dans NerdDinner.Injection de dépendances dans NerdDinner - testant réellement votre référentiel ou votre modèle

DinnerRepository de l'application: Repo image

FakeDinnerRepository des essais: Fakes image

Ils mettent en œuvre une logique différente, ce qui est bien sûr nécessaire, l'idée clé est de mettre en œuvre ici la IDinnerRepository, et fournir différentes implémentations et membres privés. Je comprends que le test est pour le contrôleur, mais je suis préoccupé par le fait qu'il existe deux implémentations différentes de la logique d'accès aux données. Considérez n'importe quel projet qui utilise n'importe quel type de ORM, ADO.NET, SubSonic, ou n'importe quelle saveur d'accès aux données que vous aimez. Oui, vous pouvez configurer votre faux dépôt pour qu'il corresponde au véritable dépôt. Mon souci est qu'au fil du temps, les détails de mise en œuvre dans le repo réel changent. Peut-être une faute de frappe, ou d'autres modifications importantes de détail de l'implémentation dans la requête . Cela conduit à un décalage potentiel de la logique dans le modèle entre le faux et le véritable repo. L'inquiétude est que la mise en œuvre du repo réel et le repo de test ne sont plus synchronisés.

Questions:

  • Comment voulez-vous tester le modèle dans ce cas?
  • Est-il approprié de tester le modèle?
  • Est-ce une question de discipline que de veiller à ce que votre test réponde à la mise en œuvre de la logique métier?

Répondre

4

Ceci n'est probablement pas une réponse complète à votre question, mais j'essaierai d'en faire partie. L'interface - dans ce cas, IDinnerRepository - doit être considérée comme un contrat . Cela signifie que toute mise en œuvre doit remplir ce contrat. Si la méthode est FindAllDinners(), c'est essentiellement ce qu'elle devrait faire. Un faux référentiel utilisé pour les tests unitaires peut généralement être beaucoup plus simple que le vrai (en utilisant un dictionnaire par exemple), donc garder le rythme de l'implémentation réelle ne devrait pas être considéré comme un problème, plutôt le voir comme une exigence.

La raison pour laquelle le faux dépôt existe en premier lieu est le test. Fondamentalement, tout ce qui peut être testé devrait être testé. Et sortir la base de données de l'équation est le point d'un faux dépôt en mémoire. L'accès aux données n'est pas le point du test, nous le remplaçons donc. Le faux référentiel est beaucoup plus rapide à configurer et à utiliser, et nous pouvons facilement nous assurer que le dépôt est dans un état qu'il doit être pour que le code testé passe. Donc, ce que vous faites est de transmettre au modèle une copie de votre faux dépôt dans vos tests unitaires, et assurez-vous que tout ce qui se passe dans le code du modèle est reflété dans le faux référentiel.

Je pense que vous constaterez qu'en pratique, il ne sera pas difficile de garder les référentiels synchronisés. Si les exigences changent, vous allez changer l'interface et les deux implémentations devront changer.Si les intentions changent, vous arriverez probablement à un point où vos tests unitaires commencent à se casser.

Espérons que cela aide!

+0

Merci Rune. Ça a du sens. Je suppose que la base de la question est: devriez-vous tester votre accès aux données? On dirait que vous dites «non». –

+0

C'est en fait l'une de ces choses que je lutte avec moi-même en tant que début TDDer. De la façon dont je le comprends actuellement, vos tests unitaires devraient laisser seul l'accès réel aux données, alors que c'est apparemment une bonne idée d'avoir des tests d'intégration qui vérifient également que l'accès aux données fonctionne correctement. Ces tests d'intégration seront plus lents, mais cela devrait être acceptable car ils ne seront probablement pas exécutés aussi souvent que les tests unitaires "purs". –

2

Cela ne sert à rien que FakeDinnerRepository teste du code nécessitant un IDinnerRepository. Ne pas tester DinnerRepository lui-même. Si nous utilisions un vrai référentiel de dîners pour tester des choses comme le DinnerController, nous testerions non seulement la fonctionnalité de DinnerController, mais aussi l'accès aux données lui-même. Bien que les bits d'accès aux données devraient certainement être testés, ils ne devraient pas être testés dans les tests du contrôleur de dîner. Le test de votre accès aux données est un sujet plutôt controversé. Je crois que la raison pour laquelle la plupart des gens laissent de côté leurs tests unitaires est simplement que cela prend beaucoup plus de temps à exécuter. Avoir à interroger la base de données ajoutera une tonne de temps à vos tests que la plupart des développeurs préfèrent ne pas supporter.

Que votre accès aux données soit testé dans des tests unitaires ou dans des tests fonctionnels plus formels, c'est à vous de décider. Mais il doit certainement être testé. Personnellement, je suis fan des tests unitaires transactionnels pour la couche d'accès aux données. Assurez-vous simplement de ne tester que vos requêtes et de ne pas tester que votre ORM fonctionne comme il le devrait (c'est le travail des ORMs).

Questions connexes