Chez Laravel-France nous aimons écrire des tests et comme beaucoup de développeurs Laravel nous utilisons quotidiennement le couple PHPunit / Mockery.
Mockery a beau être la solution plébiscitée par PHPunit, il n'est pourtant pas le seul package existant permettant de créer des doublures (aka mock), Il existe des alternatives tout aussi robustes à notre disposition, c'est le cas du package que nous allons découvrir aujourd’hui : Prophecy.
phpspec/prophecy se décrit comme une solution “dogmatique” permettant de créer des puissants et flexibles mock dans vos tests.
Nous allons voir ce que le package propose et comment l'utiliser conjointement avec PHPunit.
Installation
Prophecy nécessite au minimum une version 7.2 de PHP et s'installe depuis composer :
1composer require phpspec/prophecy --dev
Une fois installé, le package est directement disponible dans vos tests, aucune configuration supplémentaire de PHPunit n'est nécessaire.
Utilisations basiques
Pour commencer, nous allons créer une nouvelle prophétie de l'objet que nous souhaitons "mocker", dans notre cas une class BarService
.
1$prophet = new \Prophecy\Prophet();2 3$prophecy = $prophet->prophesize(BarService::class);
Nous devons ensuite manipuler cette instance de $prophecy
pour configurer le comportement de notre futur mock.
Par exemple, déterminons ce que doit retourner la méthode bar
du BarService
en fonction des arguments que le mock recevra :
1$prophecy->bar('a')->willReturn('aaa');2$prophecy->bar('b')->willReturn('bbb');
Si la méthode bar reçoit un argument 'a' : retourner 'aaa'
Une fois notre prophecy correctement configuré, la méthode reveal
permet d'appliquer les différentes contraintes et d'obtenir la doublure !
1$barService = $prophecy->reveal();2 3$barService->bar('a'); // aaa4$barService->bar('b'); // bbb5$barService->bar('c'); // null6$barService->bar(); // null
Avec Prophecy, il n'est nullement nécessaire de configurer tous les cas d'usage, utiliser la méthode bar
de notre doublure avec un argument inattendu retournera NULL
!
Des arguments
Notre précédent exemple était simple mais souffre d'une certaine rigidité, pour gagner en souplesse Prophecy dispose d'une class Argument
permettant de configurer le comportement de vos doublures de manière bien plus dynamique, toujours basé sur les arguments que recevront les méthodes !
1use Prophecy\Argument; 2use Prophecy\Prophet; 3 4$prophet = new Prophet(); 5 6$prophecy = $prophet->prophesize(BarService::class); 7 8$prophecy->bar(Argument::type('string'))->will(function ($arguments) { 9 return true;10});11 12$prophecy->bar(Argument::type('integer'))->will(function ($arguments) {13 return false;14});
Si la méthode bar reçoit un string : retourner 'true'
Cette class Argument
contient bien d'autres méthode pour configurer vos doublures : is
, exact
, in
, notIn
... Vous trouverez toutes ces alternatives dans le fichier Prophecy\Argument.php
.
1$barService = $prophecy->reveal();2 3$barService->bar('a'); // true4$barService->bar(1); // false5$barService->bar(false); // null6$barService->bar(); // null
L'une des forces de Prophecy est sa grande modularité, vous pouvez facilement créer votre propre class Argument en implémentant le contratTokenInterface
.
Vous pourrez ainsi créer des arguments relatifs à votre métier et réutilisable dans plusieurs tests !
Des prédictions
Pour finir, Prophecy propose de vérifier l’accès aux méthodes de votre doublure avec des prédictions.
1$prophet = new Prophecy\Prophet();2 3$prophecy = $prophet->prophesize(BarService::class);4 5$prophecy->bar()->shouldBeCalled();6$prophecy->bar('a')->shouldNotBeCalled();7$prophecy->bar('b')->shouldBeCalledTimes(count: 3);
Il sera ensuite nécessaire de vérifier ces prédictions en appelant la méthode checkPredictions
.
1$prophet->checkPredictions();
Allez plus loin
Bien que moins populaire que Mockery, Prophecy reste une solution alternative intéressante pour créer vos doublures en offrant sa propre vision, un peu différente, de ce que doit être un "mock" .
Vous pouvez retrouver toutes les informations de ce paquet sur son dépôt Github.
A lire
Autres articles de la même catégorie
Améliorez vos tests avec Infection
Vos tests seront-ils suffisamment exhaustifs pour être à l'épreuve de mutations ?
Mathieu De Gracia
Une façon différente d’organiser son application avec Laravel Actions
Présentation du paquet lorisleiva/laravel-actions mettant en avant une façon différente d'organiser le code
Marc COLLET
Laravel Arkitect
Appliquez des règles d'architectures dans vos projets grace à Arkitect !
Mathieu De Gracia