Au départ il s'agit d'un modèle de conception initié par Robert Binder (Testing object-oriented systems: models, patterns, and tools, Addison-Wesley) in 1999. Un bouchon serveur est une simulation d'un objet ou d'un composant. Il doit remplacer exactement un composant dans un système pour des raisons de testabilité ou de prototypage, tout en restant léger. Il permet aux tests de tourner plus rapidement ou alors, si la classe simulée n'a pas été écrite, juste de fonctionner.
Nous avons juste besoin d'une classe préexistante, par exemple une connexion vers une base de données qui ressemblerait à...
StubDatabaseConnection. Nous pouvons alors créer des instances de cette nouvelle classe à l'intérieur de notre prototype de script...
query()]]> soit encore légale. La valeur retournée sera null, Mais nous pouvons y remédier avec...
query()]]> nous obtenons un résultat de 37. Nous pouvons choisir n'importe quelle valeur pour le résultat, par exemple un hash de résultats provenant d'une base de données imaginaire ou alors une liste d'objets persistants. Peu importe les paramètres, nous obtenons systématiquement les même valeurs chaque fois qu'ils ont été initialisés de la sorte : ça ne ressemble peut-être pas à une réponse convaincante venant d'une connexion vers une base de données. Mais pour la demi-douzaine de lignes d'une méthode de test c'est souvent largement suffisant.
Sauf que les choses ne sont que rarement aussi simples. Parmi les problèmes les plus courants on trouve les itérateurs : le renvoi d'une valeur constante peut causer une boucle infini dans l'objet testé. Pour ceux-ci nous avons besoin de mettre sur pied une suite de valeurs. Prenons par exemple un itérateur simple qui ressemble à...
false. Une simulation est possible avec...
next() sur l'itérateur bouchonné il va d'abord renvoyer "First string", puis au second appel c'est "Second string" qui sera renvoyé. Finalement pour tous les autres appels, il s'agira d'un false. Les valeurs renvoyées successivement ont priorité sur la valeur constante renvoyé. Cette dernière est un genre de valeur par défaut.
Une autre situation délicate est une opération get() surchargée. Un exemple ? Un porteur d'information avec des pairs de clef / valeur. Prenons une classe de configuration...
getValue() et que nous voulons des résultats différents suivant la clef. Par chance les bouchons ont un système de filtre...
getValue() avec...
Vous pouvez définir un argument par défaut avec...
Il y a des fois où l'on souhaite qu'un objet spécifique soit servi par le bouchon plutôt qu'une simple copie. La sémantique de la copie en PHP nous force à utiliser une autre méthode pour cela. Vous êtes peut-être en train de simuler un conteneur par exemple...
get(12)]]> est appelé il renverra le même $thing.
Ces trois facteurs, ordre, paramètres et copie (ou référence), peuvent être combinés orthogonalement. Par exemple...
$stuff ne sera renvoyé qu'au troisième appel et seulement si deux paramètres étaient indiqués, avec la contrainte que le second de ceux-ci soit l'entier 1. N'est-ce pas suffisant pour des situations de prototypage simple ?
Un dernier cas critique reste celle d'un objet en créant un autre, connu sous le nom du modèle factory - fabrique. Supposons qu'après une requête réussie à notre base de données imaginaire, un ensemble de résultats est retourné sous la forme d'un itérateur, chaque appel à next() donnant une ligne et à la fin un false.
Au premier abord, ça donne l'impression d'être cauchemardesque à simuler. Alors qu'en fait tout peut être bouchonné en utilisant les mécanismes ci-dessus.
Voici comment...
$connection est appelé avec la bonne query() que le $result sera renvoyé après le troisième appel à next(). Cela devrait être suffisant pour que notre classe UserFinder, la classe effectivement testée à ce niveau, puisse s'exécuter comme il faut. Un test très précis et pas une seule base de données à l'horizon.
Il y a d'autres options additionnelles à la création d'un bouchon. Au moment de la génération nous pouvons changer le nom de la classe...
next() et isError() peuvent maintenant renvoyer des ensembles de valeurs exactement comme si elles existaient dans la classe originale.
Un moyen encore plus ésotérique de modifier les bouchons est de changer le joker utilisé par défaut pour la correspondance des paramètres.