Un adapteur générique pour appeler les fonctions natives de PHP
L’adaptateur (adapter en anglais) est l’un des design patterns les plus connus et utilisés en programmation. “Il permet de convertir l’interface d’une classe en une autre interface que le client attend. L’adaptateur fait fonctionner ensemble des classes qui n’auraient pas pu fonctionner sans lui, à cause d’une incompatibilité d’interfaces” (définition Wikipedia).
Il ne s’agit ni plus ni moins que d’un proxy qui va se charger de faire des appels d’une classe à un autre en transformant les données dans le format attendu. Les adaptateurs sont très utiles pour l’écriture de tests unitaires car ils permettent au travers de l’injection de dépendances d’être remplacé par un mock. C’est un cas d’utilisation très pratique lorsque l’on souhaite tester des blocs de code faisant appel à des fonctions natives de PHP.
Par exemple, si l’on souhaite lire un fichier de configuration, nous pourrions écrire le code suivant :
Le code ci-dessus pose problème, car il est impossible de contrôler l’exécution
de la méthode file_get_contents
. Si le test échoue, cela ne sera pas forcément
lié au code qui a été écrit, mais peut-être au système de fichiers qui est
indisponible au moment du test.
On peut alors écrire le test en utilisant un adaptateur :
De cette manière, le code devient facilement testable, puisqu’il suffira
d’utiliser un mock de la classe fileAdapter
implémentant la méthode
getFileContent
.
C’est d’ailleurs en jetant un oeil dans le code source d’Atoum, un framework de tests unitaires (que je recommande vivement) que j’ai découvert un adaptateur générique permettant de tester naturellement les fonctions natives de PHP (également présenté dans un très bon article de Julien BIANCHI).
Voici le code de l’adaptateur :
Cette classe est très astucieuse et fait appel “aux méthodes magiques” de PHP afin de rediriger les appels de l’adaptateur vers les fonctions natives du langage. De cette manière, plus besoin de créer une multitude de classes adaptateurs pour garantir que l’ensemble de notre code soit testable unitairement.
Attention toutefois à ne pas en abuser, les adaptateurs comme tout principe de programmation doivent être utilisé de manière judicieuse.