Un objet fantaisie partiel n'est ni plus ni moins qu'un modèle de conception pour soulager un problème spécifique du test avec des objets fantaisie, celui de placer des objets fantaisie dans des coins serrés. Il s'agit d'un outil assez limité et peut-être même une idée pas si bonne que ça. Elle est incluse dans SimpleTest pour la simple raison que je l'ai trouvée utile à plus d'une occasion et qu'elle m'a épargnée pas mal de travail dans ces moments-là.
Quand un objet en utilise un autre il est très simple d'y faire circuler une version fantaisie déjà prête avec ses attentes. Les choses deviennent un peu plus délicates si un objet en crée un autre et que le créateur est celui que l'on souhaite tester. Cela revient à dire que l'objet créé devrait être une fantaisie, mais nous pouvons difficilement dire à notre classe sous test de créer un objet fantaisie plutôt qu'un "vrai" objet. La classe testée ne sait même pas qu'elle travaille dans un environnement de test.
Par exemple, supposons que nous sommes en train de construire un client telnet et qu'il a besoin de créer une socket réseau pour envoyer ses messages. La méthode de connexion pourrait ressemble à quelque chose comme...
La première solution est de passer la socket en tant que paramètre, ce qui force la création au niveau inférieur. Charger le client de cette tâche est effectivement une bonne approche si c'est possible et devrait conduire à un remaniement -- de la création à partir de l'action. En fait, c'est là une des manières avec lesquels tester en s'appuyant sur des objets fantaisie vous force à coder des solutions plus resserrées sur leur objectif. Ils améliorent votre programmation.
Voici ce que ça devrait être...
La solution suivante est de passer l'objet créé sous la forme d'un paramètre optionnel...
Une autre solution encore est de laisser un objet fabrique s'occuper de la création...
Peut-on trouver un juste milieu ?
Il existe une technique pour palier à ce problème sans créer de nouvelle classe dans l'application; par contre elle induit la création d'une sous-classe au moment du test. Premièrement nous déplaçons la création de la socket dans sa propre méthode...
Pour le scénario de test, nous devons créer une sous-classe de manière à intercepter la création de la socket...
connect(). Autrement il pourrait donner un valeur nulle à partir de _createSocket().
Après la réalisation de tout ce travail supplémentaire le scénario de test est assez simple. Nous avons juste besoin de tester notre nouvelle classe à la place...
Bien sûr la réponse est "oui" ou alors j'aurais arrêté d'écrire depuis quelques temps déjà ! Le test précédent a représenté beaucoup de travail, mais nous pouvons générer la sous-classe en utilisant une approche à celle des objets fantaisie.
Voici donc une version avec objet fantaisie partiel du test...
generatePartial() nécessite trois paramètres : la classe à sous classer, le nom de la nouvelle classe et une liste des méthodes à simuler.
Instancier les objets qui en résultent est plutôt délicat. L'unique paramètre du constructeur d'un objet fantaisie partiel est la référence du testeur unitaire. Comme avec les objets fantaisie classiques c'est nécessaire pour l'envoi des résultats de test en réponse à la vérification des attentes.
Une nouvelle fois le constructeur original n'est pas lancé. Indispensable dans le cas où le constructeur aurait besoin des méthodes fantaisie : elles n'ont pas encore été initiées ! Nous initions les valeurs retournées à cet instant et ensuite lançons le constructeur avec ses paramètres normaux. Cette construction en trois étapes de "new", suivie par la mise en place des méthodes et ensuite par la lancement du constructeur proprement dit est ce qui distingue le code d'un objet fantaisie partiel.
A part pour leur construction, toutes ces méthodes fantaisie ont les mêmes fonctionnalités que dans le cas des objets fantaisie et toutes les méthodes non fantaisie se comportent comme avant. Nous pouvons mettre en place des attentes très facilement...
Les méthodes issues d'un objet fantaisie n'ont pas besoin d'être des méthodes fabrique, Il peut s'agir de n'importe quelle sorte de méthode. Ainsi les objets fantaisie partiels nous permettent de prendre le contrôle de n'importe quelle partie d'une classe, le constructeur excepté. Nous pourrions même aller jusqu'à créer des fantaisies sur toutes les méthodes à part celle que nous voulons effectivement tester.
Cette situation est assez hypothétique, étant donné que je ne l'ai jamais essayée. Je suis ouvert à cette possibilité, mais je crains qu'en forçant la granularité d'un objet on n'obtienne pas forcément un code de meilleur qualité. Personnellement j'utilise les objets fantaisie partiels comme moyen de passer outre la création ou alors de temps en temps pour tester le modèle de conception TemplateMethod.
Pour choisir le mécanisme à utiliser, on en revient toujours aux standards de code de votre projet.