Mocks et fixtures dans les tests PHP : le guide pour des tests unitaires sereins

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Pourquoi tester sans mocks, c'est comme cuisiner sans sel

\n\n

Imaginez que vous développez une application qui envoie des notifications par email, interagit avec une base de données et consomme une API externe. Comment tester tout cela sans mocks ni fixtures en PHP ? Vous devriez à chaque fois envoyer de vrais emails, créer des enregistrements de test dans la BDD et attendre la réponse d'un service externe. C'est lent, peu fiable et tout simplement inefficace.

\n\n

C'est là qu'interviennent les test doubles — des substituts d'objets réels. Dans l'écosystème PHP, on utilise principalement : les mocks pour vérifier les interactions et les fixtures pour préparer les données. Voyons concrètement comment cela fonctionne.

\n\n

Mock vs Stub vs Fake : ne mélangez pas tout

\n\n

Avant de plonger dans le code, clarifions les concepts. Dans le monde des tests unitaires PHP, on distingue trois types de substituts :

\n\n
    \n
  • Stub (bouchon) — retourne des données prédéfinies. Vous testez que votre code traite correctement ces données.
  • \n
  • Mock (simulation) — non seulement retourne des données, mais vérifie aussi comment votre système appelle les méthodes : combien de fois, avec quels arguments, dans quel ordre.
  • \n
  • Fake (fausse implémentation) — une implémentation simplifiée mais fonctionnelle (par exemple, une base de données en mémoire).
  • \n
\n\n

Avec PHPUnit, le standard de facto pour tester du code PHP, ces notions sont souvent mélangées. Mais soyons précis : les mocks en PHP sont ceux où vous définissez des attentes (expectations).

\n\n

Créer votre premier mock avec PHPUnit

\n\n

Prenons un exemple : une classe Mailer qui envoie des emails. Nous voulons vérifier que le service d'inscription appelle la méthode send() exactement une fois avec les bonnes données.

\n\n
<?php\nuse PHPUnit\\Framework\\TestCase;\n\nclass UserRegistrationTest extends TestCase\n{\n    public function testSendWelcomeEmailOnRegistration(): void\n    {\n        // Création d'un mock pour Mailer\n        $mailer = $this->createMock(Mailer::class);\n        \n        // Définition de l'attente : la méthode send sera appelée 1 fois\n        $mailer->expects($this->once())\n               ->method('send')\n               ->with(\n                   $this->equalTo('user@example.com'),\n                   $this->stringContains('Bienvenue')\n               );\n        \n        $service = new UserRegistrationService($mailer);\n        $service->register('user@example.com', 'password123');\n    }\n}\n
\n\n

Remarque importante : nous ne vérifions pas que l'email a réellement été envoyé. Nous vérifions que notre code a tenté de l'envoyer — c'est l'essence même des mocks dans les tests PHP. Si la méthode send() n'est pas appelée (ou appelée deux fois), le test échoue.

\n\n

La méthode expects et ses possibilités

\n\n

PHPUnit offre une API riche pour configurer les attentes :

\n\n
    \n
  • $this->once() — exactement un appel
  • \n
  • $this->exactly(3) — exactement trois appels
  • \n
  • $this->atLeastOnce() — au moins un appel
  • \n
  • $this->never() — la méthode ne doit pas être appelée
  • \n
\n\n

Pour les arguments, utilisez des contraintes (matchers) :

\n\n
$mailer->expects($this->once())\n       ->method('send')\n       ->with(\n           $this->callback(function($email) {\n               return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;\n           }),\n           $this->anything() // le second argument peut être n'importe quoi\n       );\n
\n\n

Fixtures en PHP : préparez les données avant qu'elles ne soient nécessaires

\n\n

Les fixtures sont un état de données prédéfini dans lequel se trouve le système avant l'exécution d'un test. Avec PHPUnit, on utilise les méthodes setUp() et

Blogs

Book Recommendations