# php-vcr enregistre une réponse HTTP externe une fois, puis la rejoue en test

> Plutôt qu'un mock écrit ligne à ligne, php-vcr enregistre une vraie réponse HTTP puis la rejoue automatiquement. Principe des cassettes, mise en place et limites.

- Auteur : WordPress Développement
- Publié le : 2020-11-05
- Mis à jour le : 2020-11-05
- Catégorie : Tests
- URL : https://www.wpmoderne.fr/tests/php-vcr-cassettes-http-tests/

## L’essentiel

- Le premier passage enregistre la vraie réponse dans une cassette au format YAML
- Les passages suivants rejouent la cassette sans requête réseau
- Une cassette obsolète doit être supprimée manuellement pour forcer un nouvel enregistrement

« Record once, replay forever » : c'est le principe résumé sur la page du projet php-vcr, une bibliothèque qui traite les appels HTTP sortants comme une bande magnétique qu'on enregistre puis qu'on rejoue. L'idée vient d'une bibliothèque Ruby plus ancienne du même nom, portée ici pour l'écosystème PHP.

Pour un développeur habitué à écrire des mocks HTTP à la main, ligne par ligne, avec un tableau de réponses simulées à maintenir manuellement, php-vcr change la logique : au lieu de deviner à quoi ressemble une réponse d'API, on capture la vraie réponse une seule fois, puis on la rejoue indéfiniment sans jamais retoucher au réseau. Ce billet ne traite pas les webhooks entrants ni un service tiers en particulier ; il présente le mécanisme général.

## Le premier passage : enregistrer une cassette

Une cassette (« cassette » dans le vocabulaire de php-vcr) est un fichier qui stocke la requête envoyée et la réponse reçue. La bibliothèque s'installe via Composer et s'active autour du test :

```
use VCR\VCR;

class Test_Client_Meteo extends PHPUnit\Framework\TestCase {

    public function test_recupere_temperature_ville() {
        VCR::turnOn();
        VCR::insertCassette( 'meteo_paris' );

        $client = new Client_Meteo();
        $temperature = $client->recuperer_temperature( 'Paris' );

        $this->assertIsFloat( $temperature );

        VCR::eject();
        VCR::turnOff();
    }
}
```

À la première exécution, aucune cassette n'existe encore : php-vcr laisse passer la requête HTTP réelle, capture intégralement la réponse du service, et l'écrit dans un fichier YAML sous `tests/cassettes/meteo_paris.yml`.

## Les passages suivants : zéro appel réseau

Dès que la cassette existe, php-vcr intercepte la requête sortante avant qu'elle n'atteigne le réseau et renvoie directement le contenu enregistré. Le test devient alors reproductible à l'identique, rapide, et fonctionne même sans connexion internet, ce qui est particulièrement utile en intégration continue.

> L'essentiel à retenir : Le premier passage enregistre la vraie réponse dans une cassette au format YAML ; Les passages suivants rejouent la cassette sans requête réseau ; Une cassette obsolète doit être supprimée manuellement pour forcer un nouvel enregistrement

```
- request:
    method: GET
    url: https://api.meteo-exemple.test/v1/temperature?ville=Paris
  response:
    status:
      code: 200
    headers:
      Content-Type: application/json
    body: '{"temperature": 14.2, "unite": "celsius"}'
```

Ce fichier, versionné avec le code, devient une trace exacte du contrat observé avec le service externe à un instant donné. Il peut être relu par n'importe quel membre de l'équipe sans avoir besoin d'accès aux identifiants du service réel.

## Comparaison avec un mock écrit à la main

Un mock manuel demande de deviner ou de reconstituer la structure exacte d'une réponse JSON, avec le risque d'oublier un champ que le service renvoie réellement mais que le développeur n'a pas anticipé. La cassette, elle, capture la réponse telle qu'elle existe vraiment, avec ses en-têtes, son code de statut et sa structure complète, sans reconstruction manuelle sujette à erreur.

- Fiabilité supérieure : la cassette reflète un échange réel, pas une supposition.
- Rapidité : aucune latence réseau une fois la cassette enregistrée.
- Contrepartie : une cassette n'est jamais réévaluée automatiquement si le service change de format de réponse.

## Gérer l'obsolescence d'une cassette

C'est la limite centrale du mécanisme : si le service externe modifie sa réponse (un champ renommé, un nouveau format de date), la cassette continue de rejouer l'ancienne version indéfiniment, et le test reste vert alors que le code réel échouerait désormais face au vrai service. Il n'existe pas de détection automatique de cette dérive.

> Une cassette doit être considérée comme une donnée versionnée à durée de vie limitée, pas comme une vérité permanente : la supprimer et la régénérer périodiquement fait partie de l'entretien normal d'une suite qui en dépend.

### Régénérer une cassette devenue obsolète

1. Supprimer le fichier de cassette concerné dans le dossier dédié.
2. Relancer le test une première fois avec un accès réseau réel disponible, pour forcer un nouvel enregistrement.
3. Vérifier le contenu du fichier régénéré avant de le committer, notamment si la réponse contient une donnée sensible à filtrer.

Sur ce dernier point, php-vcr propose des filtres de configuration pour retirer une clé d'API ou un jeton d'authentification de la cassette avant son enregistrement sur disque, ce qui évite de committer un secret par inadvertance.

## En résumé

php-vcr remplace le mock HTTP écrit à la main par une capture réelle rejouée ensuite sans réseau, ce qui gagne en fidélité et en vitesse d'exécution. La contrepartie est un entretien régulier des cassettes, faute de quoi un test peut rester vert longtemps après que le service réel a changé de comportement.
