TypeMock: mock everything!
Tester du code Legacy
Il y a quelques temps, j’ai initié une série de blog post sur un sujet toujours d’actualité : comment tester unitairement une application Legacy quand les techniques de bases ne sont plus suffisantes.
Le problème qui se pose était le suivant :
- j’ai besoin d’un code testable pour faire du TDD et donc le modifier de manière safe.
- mon code Legacy n’est pas testable et je ne peux donc pas le modifier sans prendre de risque.
Bref, on boucle et on est bloqué (le fameux serpent qui se mord la queue).
L’idée était donc de casser cette boucle en utilisant un outil assez puissant pour intégrer un filet de sécurité (harnet tests) sans faire la moindre modification pour ensuite remettre le code dans un état propre.
Les étapes sont donc les suivantes :
- introduire des tests et couvrir le SUT (system Under Test) sans le modifier pour ne pas faire de régression
- modifier le code pour le rendre plus propre
- introduire des tests s’appuyant sur des tests doubles classiques (fake, mock, stub,…)
- supprimer les premiers tests
J’ai tenté de démontrer cette méthode en utilisant l’outil proposé par Microsoft, le Fakes framework et au final je dois dire que je reste assez mitigé : l’approche choisie par MS de générer des proxies qui ont des noms de type « FakesXXX » ou « ShimXXX » est pénible car elle nous empêche d’utiliser des outils de refactoring lorsque l’on souhaite renommer une méthode ou une classe et nous force à régénérer toutes nos « fakes assemblies »…
Donc, l’approche est pas mal mais l’outil présente des défauts qui le rendent difficilement utilisable dans un « vrai projet ».
TypeMock
J’ai eu l’occasion de tester TypeMock ces derniers jours et je dois dire que j’ai été agréablement surpris ! Il permet de faire quasiment les mêmes choses et même plus tout en gommant les éléments qui me gênaient avec le FakesFramework !
TypeMock Isolator (dans sa version essential…qui n’est pas gratuite…) comme le fakeFramework va vous permettre de faire de la redirection d’appel au runtime (runtime interception) : en gros, si vous appeler une méthode ou instancier une classe, il va vous permettre de rediriger l’appel vers du code spécifique à votre tests. Cela signifie donc : plus besoin d’avoir du code découplé pour les tests…car on est en mesure de quasiment tout rediriger et donc de tout isoler !
A première vue, cela parait cool mais c’est très dangereux car l’objectif du TDD est aussi d’aboutir à un design de qualité. Utiliser TypeMock nous permet d’avoir du code crade et testé…c’est pourquoi je recommande vivement de supprimer tous les « super » mock à la fin du cycle décris ci-dessus.
Quelques exemples ici :
Vous avez des singletons (le diable du test unitaire):

Dans votre SUT, vous instancier un objet :
J’ai une méthode à tester et elle instancie un objet à l’intérieure de celle-ci :

On fait appel à des objets/méthodes du framework .net…comme la classe ConfigurationManager :

Et vous pouvez en faire encore plus (je vous invite au passage d’aller regarder la doc officielle)!
Pour finir, c’est un excellent outil (payant) pour des cas extrême et à mettre uniquement entre les mains de personnes ayant une bonne pratique du TDD et qui souhaitent s’attaquer à la problématique d’intégrer des tests sur du code Legacy bien crado.
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :