Utilisation de PHP-VCR pour Enregistrer et Rejouer les Appels d’API en PHP

Imenezzine
6 min readJan 10, 2024

--

Aujourd’hui, je vais partager avec vous mon expérience avec une bibliothèque que je trouve extraordinaire, car elle vous fera économiser du temps et de l’argent.

Lorsque vous développez des applications PHP qui interagissent avec des API externes, les tests d’intégration peuvent devenir compliqués. Les appels réels aux API peuvent être coûteux, dépendants de la disponibilité des serveurs et ne garantissent pas toujours la cohérence des résultats.

Dans une de mes missions, nous avons travaillé sur une application qui synchronise des produits entre un PIM (Product Information Management) et un site E-commerce. Dans ce contexte, les tests d’intégration étaient particulièrement fastidieux. C’est là qu’intervient PHP-VCR, une bibliothèque PHP qui permet d’enregistrer et de rejouer les requêtes HTTP, simplifiant ainsi les tests d’intégration. Dans cet article, nous explorerons deux façons d’utiliser PHP-VCR.

Méthode 1 : Utilisation de PHP-VCR avec des Méthodes Statiques

Étape 1 : Installation de PHP-VCR

La première étape pour utiliser PHP-VCR consiste à l’installer dans votre projet à l’aide de Composer. Exécutez la commande suivante dans votre terminal :

composer require php-vcr/php-vcr --dev

Étape 2 : Configuration de PHP-VCR

Après l’installation, vous devez configurer PHP-VCR pour qu’il enregistre les requêtes HTTP. Vous pouvez utiliser les méthodes statiques de PHP-VCR pour activer et désactiver l’enregistrement, définir le répertoire de stockage des cassettes (captures) et plus encore.

Dans l’un de mes ancien articles j’ai cité qu’on a utilisé la TDD (Test Driven Design) pour construire notre domaine (vous pouvez consulter l’article via ce lien). Cette approche consiste à écrire nos tests avant de se plonger dans le code et de le faire passer step by step en écrivant le minimum du code.

On va donc écrire notre test avec behat dans mon cas et une fois le test passe au vert on ajoute tout simplement le tag @vcr

En exécutant le test une autre fois on va avoir un nouveau fichier crée (notre cassette) avec l’enregistrement de la request envoyée et la response

C’est magique ! Non ?

Étape 3 : Enregistrement et Reproduction des requêtes

Derrière cette magie il y a une simple configuration à faire. 😉

En utilisant Behat, vous pouvez configurer le setup VCR en utilisant les annotations @BeforeScenario et @AfterScenario pour activer et désactiver l'enregistrement. Vous pouvez utiliser la méthode VCR::turnOn() pour activer l'enregistrement, puis effectuez vos requêtes HTTP normalement.

Du coup dans @BeforeScenario vous devez configurer PHP-VCR pour qu’il enregistre les requêtes HTTP, en utilisant tout simplement la méthode VCR::turnOn() pour activer l'enregistrement, puis effectuez vos requêtes HTTP normalement.

la méthode VCR::insertCassette(‘example’) va enregistrer les requêtes et les réponses dans une cassette nommée ‘example’ dans le répertoire de votre choix. La cassette agit comme un enregistrement des interactions HTTP.

  private bool $vcrOn = false;

/**
* @BeforeScenario
*/
public function setupVCR(BeforeScenarioScope $scenarioEvent): void
{
if ($scenarioEvent->getScenario()->hasTag('vcr')) {
\VCR\VCR::turnOn();
$this->vcrOn = true;
$scenarioCassette = strtolower(str_replace(' ', '_', $scenarioEvent->getScenario()->getTitle()));
$suiteName = $scenarioEvent->getSuite()->getName();
\VCR\VCR::insertCassette($suiteName.'/'.$scenarioCassette.'.yaml');
}
}

Après avoir effectué la requête et enregistré les données associées dans la cassette, dans la step @AfterScenarionous utilisons la méthode statique VCR::eject() pour arrêter l’enregistrement des requêtes. Cela signifie que les interactions HTTP seront dorénavant lues à partir de la cassette au lieu de réaliser de véritables requêtes HTTP.

Enfin, nous utilisons la méthode statique VCR::turnOff() pour désactiver complètement l’interception des requêtes HTTP. À partir de ce moment, PHP-VCR ne surveillera plus les requêtes sortantes.

   /**
* @AfterScenario
*/
public function ejectCassette(): void
{
if ($this->vcrOn) {
\VCR\VCR::eject();
}
\VCR\VCR::turnOff();
}

Pour aller plus loin PHP-VCR vous donne la main de personnaliser votre configuration:

  • Vous pouvez personnaliser la manière dont PHP-VCR correspond aux demandes à l’aide de l’option de configuration. Répertoriez tous les noms d’un matcher qui doit être activé, en utilisant enableRequestMatchers();
  • PHP-VCR vous permet de définir vos propres request matchers en tant que fonctions de rappel(callback functions) et de les combiner avec celles existantes, en utilisant addRequestMatcher();
  • Comme je l’ai mentionné précédemment, les cassettes seront enregistrées dans le répertoire de votre choix en utilisant setCassettePath();
  • PHP-VCR stocke les interactions HTTP sur disque au format YAML ou JSON. Par défaut, PHP-VCR utilise le stockage YAML. Vous pouvez le préciser en utilisant la méthode setStorage();
  • Le mode d’enregistrement détermine la manière dont les demandes sont traitées. Il nous faut juste d’ajouter la méthode setMode();avec le mode enregistrement souhaité. Les modes disponibles sont :

​ ​ ​​​ ​​ ​​​ ​ ​​ ​ ​​​ ​ ​​ ​ ​​​ ​ ​ -new_episodes autorise toujours les nouvelles requêtes HTTP, mode ​ ​ ​​​ ​​ ​​​ ​ ​​ ​ ​​​ ​ ​​ ​ ​​​ ​ par defaut

​ ​ ​​​ ​​ ​​​ ​ ​​ ​ ​​​ ​ ​​ ​ ​​​ ​ ​- once autorisera de nouvelles requêtes HTTP la première fois que la ​ ​ ​​​ ​​ ​​​ ​ ​​ ​ ​​​ ​ ​​ ​ ​​​ ​ ​cassette est créée, puis lancera une exception par la suite.

​ ​ ​​​ ​​ ​​​ ​ ​​ ​ ​​​ ​ ​​ ​ ​​​ ​- none n’autorisera jamais de nouvelles requêtes HTTP.

 \VCR\VCR::configure()    
->addRequestMatcher(
'custom_body_matcher',
new CustomBodyMatcher()
)
->enableRequestMatchers(['method', 'url', 'query_string', 'custom_body_matcher', 'post_fields'])
->enableLibraryHooks(['curl'])
->setCassettePath(dirname(__DIR__, 2).'/tests/Environment/IO/cassettes')
->setStorage('yaml')
->setMode('once');

Méthode 2 : Utilisation de PHP-VCR avec PHPUnit

Étape 1 : Installation de PHP-VCR avec PHPUnit

Pour utiliser PHP-VCR avec PHPUnit, commencez par installer les dépendances nécessaires :

composer require phpunit/phpunit php-vcr/phpunit-testlistener-vcr --dev

Étape 2 : Configuration de PHPUnit

Dans votre fichier de configuration PHPUnit (généralement phpunit.xml), ajoutez le listener PHP-VCR pour utiliser PHP-VCR avec PHPUnit.

<phpunit>
<!-- ... autres configurations ... -->
<listeners>
<listener class="VCR\PHPUnit\TestListener\VCRTestListener" file="vendor/php-vcr/phpunit-testlistener-vcr/src/VCRTestListener.php" />
</listeners>
</phpunit>

Étape 3 : Écriture de Tests avec PHP-VCR

Maintenant, vous pouvez écrire des tests PHPUnit qui utilisent PHP-VCR pour enregistrer et rejouer des requêtes HTTP. Voici un exemple de test :

use PHPUnit\Framework\TestCase;
use GuzzleHttp\Client;
use VCR\VCR;

class MyApiTest extends TestCase
{
public function setUp(): void
{
// On initialise PHP-VCR avant chaque test
VCR::turnOn();
}

public function tearDown(): void
{
// On désactive PHP-VCR après chaque test
VCR::turnOff();
}

public function testApiCall()
{
// On configure PHP-VCR pour enregistrer les requêtes HTTP
VCR::insertCassette('testApiCall');

// Votre code de test qui effectue une requête HTTP à une API
$httpClient = new Client();
$response = $httpClient->get('https://api.example.com/data');

// Assertions sur la réponse de l'API
$this->assertEquals(200, $response->getStatusCode());

// On arrête l'enregistrement de PHP-VCR
VCR::eject();
}
}

Lorsque vous exécutez ce test, PHP-VCR enregistrera la première requête HTTP à l’API. Lorsque vous exécutez le test à nouveau, PHP-VCR utilisera la cassette enregistrée pour simuler la réponse de l’API, évitant ainsi les requêtes réelles.

Conclusion

PHP-VCR est un outil puissant pour simplifier les tests d’intégration en enregistrant et en rejouant des requêtes HTTP. Que vous choisissiez d’utiliser les méthodes statiques ou de l’intégrer avec PHPUnit, PHP-VCR peut grandement améliorer la stabilité et la cohérence de vos tests en réduisant la dépendance aux services externes. Il est particulièrement utile pour tester des intégrations avec des API tierces ou des services web. En l’utilisant judicieusement, vous pouvez rendre vos tests plus fiables et plus rapides.

--

--