[TDD] A quoi servent les mocks ?

Introduction

L’objectif d’un Mock est de pouvoir tester quelque chose qui est difficilement testable en temps normal. Prenons le cas d’une classe permettant de créer des fichiers textes, d’écrire à l’intérieur et d’en lire le contenu. C’est un exemple qui rentre tout à fait dans le cadre des Mocks : grâce à eux, on peut simuler la création d’un fichier, la présence de celui-ci, ainsi que son contenu. Concrètement, les tests exécutés grâce aux Mocks permettent de simuler le fonctionnement de la classe en question sans qu’un seul fichier soit créé et d’effectuer le traitement complet, mais pas de tester l’implémentation finale de la classe.

 

Principe de fonctionnement

L’objectif des Mocks est de placer sur l’appel à une fonction, une instruction qui va être exécutée au lieu de la réelle implémentation de la fonction. En clair, ce n’est pas le fonctionnement réel de la fonction qui va être exécuté mais le fonctionnement alternatif défini grâce au Mock. Dans notre exemple, il est possible de spécifier à l’aide du Mock que la fonction qui lit le contenu du fichier doit systématiquement renvoyer « 0 » et non le contenu réel comme le fait la vraie implémentation de la fonction ; lors de chaque appel à cette dite fonction, elle renverra donc « 0 ».

Concrètement à quoi cela sert-il ? Si le fichier dont le contenu doit être récupéré n’est pas existant ou pas accessible (peu importe la raison), sans les Mock il n’est pas possible de continuer à tester le reste du programme. Or grâce à ces derniers, le contenu du fichier peut être virtuellement récupéré et poursuivre le traitement qui en découle, tout en conservant l’appel normal à la fonction.

Il est également possible de définir un comportement alternatif à des fonctions du framework .NET. Prenons un exemple simple : un Mock peut être placé sur « DateTime.Now », afin que l’appel à cette fonction renvoie toujours le 1/1/1900. Enfin ça c’est dans la théorie, car parmi les 4 frameworks de Mocks qui sont en test ci-dessous, seuls 2 sont capables d’effectuer ce test avec succès et de façon simple.

Une autre possibilité intéressante offerte par les Mocks est le fait de pouvoir définir une valeur de retour bien précise en fonction d’un argument bien précis passé lors de l’appel à la fonction qui a été « mockée ». Concrètement, si une fonction « FichierExiste(string) » est appelée avec « toto.txt »  comme paramètre, il est possible de définir que la fonction reverra toujours « true », même si le fichier n’existe pas. Et si cette fonction est appelée avec un autre paramètre, elle va conserver son comportement normal.


Les différents frameworks testés

EasyMock

N’existe plus pour .NET, uniquement pour Java.

RhinoMock

Lien : http://ayende.com/blog

Prix de la licence : Gratuite

Pour commencer, il faut préciser que ce Framework n’est plus maintenu par son créateur ce qui la difficulté qu’il y a pour télécharger les dll à intégrer dans les projets. Au niveau du framework en lui-même : c’est celui qui présente le plus de contraintes : on ne peut pas Mocker des classes abstraites ou scellées (sealed), le seul moyen de contourner ce soucis est de faire un wrapper. On ne peut pas non plus « mocker en profondeur », ce qui présente quand même un gros point négatif. Par contre il permet de tester les classes personnalisées sans problème (à condition qu’elles ne soient pas sealed).

Le gros point négatif de ce framework réside dans la mise en place de ces mocks : pour reprendre un exemple précédent, pour tester qu’un fichier existe, avec d’autres frameworks cela demande d’écrire 2-3 lignes de code, mais avec celui-ci il en faut une dizaine.

JustMock

Lien : http://www.telerik.com

Prix de la licence : 299$ (un seul utilisateur autorisé), mais il existe une version gratuite limitée

Ce framework payant présente un bon niveau de qualité. Son principal avantage est d’avoir la documentation la plus complète et la plus précise de tous les frameworks qui sont testés ici. Ensuite, il permet de tester efficacement les mocks sur les classes et interfaces personnalisées quelle que soit la licence (gratuite ou payante). Sa version gratuite ne permets pas de mocker les objets du framework (comme le DateTime), ni de tester des méthodes ou propriété privées ou statiques, ni de faire du « mocking en profondeur ». Néanmoins la version payante le permet.

L’utilisation du framework est relativement simple, grâce à sa documentation aisément compréhensible. Le seul bémol vient de la qualité et de la lisibilité du code produit. En effet la mise en place de Mocks se fait via des fonctions anonymes et des expressions lamdba, donc le code final est assez difficile à comprendre dans le cas d’un Mock complexe. La solution pour remédier à cela est d’enrichir son code avec de nombreux commentaires.

TypeMock

Lien : http://www.typemock.com/

Prix de la licence : 799€ + 180€ pour le module ASP. Pas de version gratuite, mais une version d’essai de 30 jours

Le meilleur framework testé sans hésitation. C’est tout d’abord le seul permettant de faire tout ce dont on attend d’un framework de Mocks : du mocking de classes et d’interfaces écrites par le programmeur jusqu’au mocking d’éléments du framework .NET en passant par du « mocking en profondeur ». En outre ce framework est en fait un vrai plugin pour Visual Studio, qui enrichi ce dernier de quelques fonctionnalités bien utiles  pour les projets de test : affichage d’alertes si une fonction de test ne présente pas de fonction « Assert », comptabilisation du temps passé à écrire les tests par rapport à l’écriture du « vrai code » et bien d’autres fonctionnalités encore.

Pour finir, c’est celui qui assure la meilleure lisibilité du code en ayant un recours limité aux fonctions anonymes et qui se passe totalement des expressions lambda.

 

Glossaire

Mocking en profondeur

C’est l’action de placer un Mock sur une fonction qui est utilisée dans une autre fonction. C’est-à-dire que si j’ai une fonction appelée « SupprimerFichier(string __fichierASupprimer) » qui elle-même fait appel à la fonction « FileInfo.Delete() » et que le Mock est placé sur « FileInfo.Delete() » alors que dans ma fonction de test l’appel est effectué à « SupprimerFichier ». Le but est que la fonction « FileInfo.Delete » se comporte comme définit dans le Mock, malgré le fait qu’elle ne soit pas appelée dans la fonction de test.

© 2011 Copyright cigo-developpement.fr