Guzzle – mocking HTTP en PHP

Aujourd’hui, nous allons parler des tests unitaires, mocks, client HTTP et PHP ! đź
Sommaire
Tests unitaires
Les tests unitaires automatisĂ©s sont un outil essentiel pour garantir la stabilitĂ© d’un dĂ©veloppement et accĂ©lĂ©rer les phases de correction, d’Ă©volution ou refactoring. Cependant, pour qu’un test unitaire soit efficace, il doit s’assurer de respecter quelques recommandations (liste non-exhaustive) :
- ĂȘtre trĂšs rapide Ă exĂ©cuter : pour le lancer le plus souvent possible et avoir un feedback presque instantanĂ©
- ĂȘtre rejouable indĂ©finiment : pour le lancer le plus souvent possible
- ne tester que le composant ou la fonction Ă tester : car c’est sa raison d’ĂȘtre
Mocks
Un test unitaire ne doit donc pas tester les dépendances du composant à tester. Les deux principales raisons sont :
- Les dĂ©pendances ont leurs propres tests unitaires. Il n’est donc pas nĂ©cessaire de les tester une seconde fois.
- Si une dépendance contient un bug, est-ce que le composant testé a un bug ? Non !
Afin de rĂ©pondre Ă cette problĂ©matique, il est possible d’utiliser des techniques de mocking (ou stubing). Elles permettent de simuler le comportement d’un composant et donc d’une dĂ©pendance. Ainsi, un contrat d’utilisation du sous-composant est dĂ©fini. Le test valide le comportement du composant principal en le mettant en condition normale (ie. comportement du sous-composant attendu). L’utilisation de mocks assure la stabilitĂ© des dĂ©pendances et augmente donc celle du test unitaire.
Architecture REST
Ce qui est intĂ©ressant avec les architectures REST actuelles, c’est qu’elles reposent souvent sur un unique et mĂȘme protocole de communication : HTTP. C’est donc le protocole qui est utilisĂ© pour matĂ©rialiser les dĂ©pendances entre les composants dans ce type d’architecture. L’enjeu des tests unitaires ici est donc d’ĂȘtre capable de crĂ©er des mocks HTTP.
Et en PHP ?
Venons en maintenant Ă ce qui nous interesse : le PHP !
PHP propose des fonctions en standard pour faire des appels HTTP. NĂ©anmoins, il existe des composants plus avancĂ©s tels que Guzzle. Ce client HTTP pour PHP propose lui-mĂȘme de crĂ©er un mock HTTP.
Imaginons le composant suivant qui permet de rĂ©cupĂ©rer le dĂ©tail de ressources exposĂ©es via l’API « datas » :
class ApiBackup { public $client; public function __construct() { $this->client = new GuzzleHttp\Client();} public function exportAll() { $response = $this->client->get('https://apis.company.com/datas'); foreach($res->json()->results as $row) { $results[] = $this->client>get('https://apis.company/datas/'.$row->id); } return results; } }
CrĂ©er un test unitaire automatisĂ© de ce composant nĂ©cessite donc d’avoir une API « datas » toujours disponible, trĂšs rapide et toujours avec les mĂȘmes donnĂ©es. Autant dire : mission impossible ! C’est pourquoi nous allons « mocker » le client HTTP et crĂ©er le test uniaire suivant :
class ApiBackupTest extends PHPUnit_Framework_TestCase { public function testExportAll() { // GIVEN $apiBackup = new ApiBackup(); $mock = new GuzzleHttp\Subscriber\Mock(); $mock->addResponse('./ressources/datas_all.txt'); //contient la réponse HTTP attendue (avec 3 résultats) pour l'appel à https://apis.company.com/datas $mock->addResponse('./ressources/datas_1.txt'); // contient la réponse HTTP attendue (avec le détail de la ressource) pour l'appel à 'https://apis.company/datas/'.$row->id $mock->addResponse('./ressources/datas_2.txt'); // idem $mock->addResponse('./ressources/datas_3.txt'); // idem $apiBackup->client->getEmitter()->attach($mock); // WHEN $results = $apiBackup->exportAll(); // THEN $this->assertEquals(3,count($results)); } }
Le test unitaire ci-dessus créé un mock qui retournera toujours 3 ressources avec toujours le mĂȘme dĂ©tail. L’API « datas » ne sera pas appelĂ©e lors de l’exĂ©cution du test.
Pour explication, un fichier de réponse ressemble à ceci :
HTTP/1.1 200 OK Access-Control-Allow-Origin: * Content-Type: application/json Date: Fri, 14 Mar 2014 07:53:27 GMT Content-Length: 79 Connection: keep-alive { "results": [ {"id":"1571"}, {"id":"2349"}, {"id":"3727"}, ] }
Il est possible d’obtenir ces fichiers de rĂ©ponse HTTP avec les commandes suivantes (si l’API « datas » est dans l’Ă©tat souhaitĂ©) :
$ curl -iv --raw -o ressources/datas_all.txt 'https://apis.company.com/datas' $ curl -iv --raw -o ressources/datas_1.txt 'https://apis.company.com/datas/1571' $ curl -iv --raw -o ressources/datas_2.txt 'https://apis.company.com/datas/2349' $ curl -iv --raw -o ressources/datas_3.txt 'https://apis.company.com/datas/3727'
Vous ĂȘtes maintenant armĂ© pour industrialiser les tests unitaires de vos applications PHP qui utiliseraient le client HTTP Guzzle.
https://blog.lecacheur.com/2014/11/14/guzzle-mocking-http-en-php/https://blog.lecacheur.com/wp-content/uploads/2014/11/php-unit.jpghttps://blog.lecacheur.com/wp-content/uploads/2014/11/php-unit-150x150.jpgDĂ©veloppementmock,php,restAujourd'hui, nous allons parler des tests unitaires, mocks, client HTTP et PHP ! đź Tests unitaires Les tests unitaires automatisĂ©s sont un outil essentiel pour garantir la stabilitĂ© d'un dĂ©veloppement et accĂ©lĂ©rer les phases de correction, d'Ă©volution ou refactoring. Cependant, pour qu'un test unitaire soit efficace, il doit s'assurer de respecter...SeBSĂ©bastien LECACHEUR23r0@laposte.netAdministratorLe weblogue de SeB
Laisser un commentaire