# Tester une route REST personnalisée avec WP_REST_Request et rest_do_request

> Simulez des appels à votre route REST maison sans serveur HTTP réel, et vérifiez statut, schéma et permissions en quelques lignes de PHPUnit.

- Auteur : Clément Hadrot
- Publié le : 2020-01-29
- Mis à jour le : 2020-01-29
- Catégorie : Tests
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tests/tester-route-rest-phpunit-wp-rest-request/

## L’essentiel

- Aucune requête HTTP réelle nécessaire
- Vérifier le schéma de réponse
- Couvrir les permissions par capacité

Sur un projet pour un client qui exposait un catalogue de formations via une route REST personnalisée, l'équipe testait la route à la main avec Postman avant chaque mise en production. Le jour où un développeur a renommé un paramètre de requête sans prévenir personne, le formulaire de recherche du site a silencieusement cessé de renvoyer des résultats pendant trois jours. Un test d'intégration automatisé aurait suffi à l'attraper en quelques secondes.

WordPress fournit exactement l'outillage nécessaire pour ce genre de vérification, sans passer par un vrai serveur HTTP : la classe `WP_REST_Request` et la fonction `rest_do_request()`. Elles permettent de simuler une requête entrante, de la faire passer par le routeur REST du cœur, et d'inspecter la réponse comme si un client l'avait réellement envoyée.

## Pourquoi simuler plutôt qu'appeler un vrai point de terminaison

Faire un appel HTTP réel dans une suite de tests pose plusieurs problèmes : il faut un serveur qui tourne, l'authentification par cookie ou par application password devient pénible à automatiser, et chaque test devient lent. En passant par `rest_do_request()`, la requête traverse tout le cycle de vie REST de WordPress (permission_callback, validate_callback, sanitize_callback, callback) en restant dans le même processus PHP que le test. C'est rapide, déterministe, et cela permet d'inspecter directement l'objet `WP_REST_Response` retourné plutôt que de parser du JSON brut.

## Mettre en place le test d'intégration

La classe de base à utiliser est `WP_Test_REST_TestCase` (ou simplement `WP_UnitTestCase` si vous préférez rester générique). Il faut d'abord s'assurer que le serveur REST est initialisé avant d'envoyer une requête :

```
class Test_Formations_Route extends WP_Test_REST_TestCase {

    public function setUp(): void {
        parent::setUp();
        global $wp_rest_server;
        $wp_rest_server = new WP_REST_Server();
        do_action( 'rest_api_init' );
    }

    public function test_liste_les_formations_publiees() {
        $request  = new WP_REST_Request( 'GET', '/mon-plugin/v1/formations' );
        $request->set_param( 'categorie', 'developpement' );

        $response = rest_do_request( $request );
        $data     = $response->get_data();

        $this->assertEquals( 200, $response->get_status() );
        $this->assertIsArray( $data );
    }
}
```

> L'essentiel à retenir : Aucune requête HTTP réelle nécessaire ; Vérifier le schéma de réponse ; Couvrir les permissions par capacité

## Vérifier le statut, les en-têtes et le schéma de réponse

Une route REST bien testée ne se contente pas de vérifier le code 200. Il faut aussi contrôler la forme des données retournées, surtout si un `schema` a été déclaré via `register_rest_route()`. Quelques assertions utiles :

- `assertArrayHasKey( 'id', $item )` sur chaque élément du tableau retourné
- `assertSame( 'application/json', $response->get_headers()['Content-Type'] )` pour l'en-tête de contenu
- `$response->get_matched_route()` pour confirmer que la bonne route a été résolue en cas d'ambiguïté
- Comparaison du tableau retourné avec le schéma déclaré, via `rest_validate_value_from_schema()` côté test

## Tester les permissions et les capacités

Le `permission_callback` est souvent le point le plus fragile d'une route, et pourtant le moins testé en pratique. Il suffit de changer d'utilisateur courant avant d'envoyer la requête pour couvrir chaque cas :

```
public function test_refuse_la_creation_sans_capacite() {
    $abonne = self::factory()->user->create( array( 'role' => 'subscriber' ) );
    wp_set_current_user( $abonne );

    $request = new WP_REST_Request( 'POST', '/mon-plugin/v1/formations' );
    $request->set_param( 'titre', 'Atelier PHPUnit' );

    $response = rest_do_request( $request );

    $this->assertEquals( 401, $response->get_status() );
}
```

Il est important de tester au minimum trois profils : un visiteur non connecté, un rôle qui ne devrait pas avoir accès, et un rôle qui devrait pouvoir agir. Ce triptyque suffit à couvrir la majorité des régressions de permission_callback rencontrées sur des extensions professionnelles.

## Simuler des paramètres invalides

Enfin, un point souvent négligé : vérifier que les `validate_callback` et `sanitize_callback` déclarés dans `args` fonctionnent réellement. Un paramètre `categorie` censé n'accepter que des valeurs d'une liste fermée doit renvoyer une erreur 400 si on lui passe une valeur absurde :

```
$request->set_param( 'categorie', 'inexistante' );
$response = rest_do_request( $request );
$this->assertEquals( 400, $response->get_status() );
```

> Sur nos projets, la règle est simple : toute route REST qui accepte une écriture (POST, PUT, DELETE) doit avoir au moins un test de permission_callback avant d'être fusionnée. C'est la ligne de défense la moins chère à écrire et la plus souvent oubliée.

## En résumé

Tester une route REST personnalisée ne demande ni serveur, ni client HTTP, ni bibliothèque tierce : `WP_REST_Request` et `rest_do_request()` suffisent à couvrir le statut, le schéma et les permissions directement dans PHPUnit. Le mock des dépendances vers des API tierces appelées depuis le callback est un sujet à part entière, qui mérite son propre traitement plutôt que d'être mélangé à ces vérifications de base.
