Comme je n'ai pas vraiment d'expérience dans les tests unitaires, j'essaie de rassembler certaines règles que je vais d'abord apprendre.
Soyez prudent en apprenant des "règles" pour des problèmes que vous n'avez jamais rencontrés. Si vous rencontrez une "règle" ou une "meilleure pratique", je vous suggérerais de trouver un exemple simple de jouet où cette règle est "supposée" être utilisée, et d'essayer de résoudre ce problème vous - même , en ignorant ce que la "règle" dit.
Dans ce cas, vous pouvez essayer de créer 2 ou 3 classes simples et certains comportements à mettre en œuvre. Implémentez les classes de la manière qui vous semble naturelle et écrivez un test unitaire pour chaque comportement. Faites une liste de tous les problèmes que vous avez rencontrés, par exemple si vous aviez commencé avec des choses qui fonctionnaient dans un sens, vous deviez ensuite revenir en arrière et les changer plus tard; si vous avez du mal à comprendre comment les choses sont censées s'emboîter; si vous vous ennuyez en écrivant un message passe-partout; etc.
Ensuite, essayez de résoudre le même problème en suivant la "règle". Encore une fois, faites une liste des problèmes que vous avez rencontrés. Comparez les listes et réfléchissez aux situations qui pourraient être meilleures en suivant la règle et celles qui ne le pourraient pas.
En ce qui concerne votre question, j’ai tendance à privilégier une approche basée sur les ports et les adaptateurs , dans laquelle nous faisons une distinction entre "logique de base" et "services" (ceci est similaire à la distinction entre fonctions pures et procédures efficaces).
La logique de base consiste à calculer des éléments "à l'intérieur" de l'application, en fonction du domaine du problème. Il peut contenir des classes comme User
, Document
, Order
, Invoice
, etc. Il va bien d'avoir des classes de base appellent new
à d' autres classes de base, car ils sont les détails de mise en œuvre « internes ». Par exemple, créer un Order
peut également créer un Invoice
et un Document
détail de ce qui a été commandé. Il n'est pas nécessaire de vous moquer de cela pendant les tests, car ce sont les choses que nous voulons tester!
Les ports et les adaptateurs permettent d’interagir entre la logique principale et le monde extérieur. C'est là des choses comme Database
, ConfigFile
, EmailSender
, etc. vivent. Ce sont les choses qui rendent les tests difficiles, il est donc conseillé de les créer en dehors de la logique de base et de les transmettre au besoin (avec une injection de dépendance, ou comme arguments de méthode, etc.).
De cette façon, la logique principale (qui est la partie spécifique à l'application, où réside la logique métier importante et est soumise au plus grand nombre de désabonnements) peut être testée seule, sans avoir à se soucier des bases de données, des fichiers, des courriels, etc. Nous pouvons simplement passer quelques exemples de valeurs et vérifier que nous obtenons les bonnes valeurs de sortie.
Les ports et les adaptateurs peuvent être testés séparément, à l'aide de modèles pour la base de données, le système de fichiers, etc., sans avoir à se soucier de la logique métier. Nous pouvons simplement passer des exemples de valeurs et nous assurer qu'elles sont stockées / lues / envoyées / etc. de manière appropriée.