# Brain Monkey : tester la logique métier d’un plugin sans charger WordPress

> Charger tout le cœur WordPress pour tester une simple fonction est lent et souvent inutile. Brain Monkey permet de simuler hooks et fonctions WordPress en tests unitaires purs.

- Auteur : Clément Hadrot
- Publié le : 2020-08-25
- Mis à jour le : 2026-09-25
- Catégorie : Tests
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tests/brain-monkey-tester-sans-wordpress/

## L’essentiel

- Des tests qui s'exécutent sans base de données ni bootstrap WordPress
- Des hooks et filtres simulés avec Functionswhen()
- Une suite jusqu'à dix fois plus rapide sur la logique pure

La suite `WP_UnitTestCase` est indispensable dès qu'un test touche réellement la base de données, la boucle WordPress ou le système de permissions. Mais une grande partie du code d'un plugin n'a rien à voir avec cela : des fonctions de calcul, de formatage, de validation, qui se contentent d'appeler `apply_filters()` ou `get_option()` en passant. Faire démarrer tout WordPress pour tester ce genre de logique est un gaspillage de temps, à raison de plusieurs secondes par exécution de suite.

Le paquet [Brain Monkey](https://github.com/Brain-WP/BrainMonkey), construit au-dessus de Mockery, résout ce problème en simulant les fonctions et hooks WordPress sans jamais charger le cœur. Voici comment l'intégrer à une suite PHPUnit existante et écrire des tests réellement isolés.

## Pourquoi séparer logique métier et tests d'intégration

Un plugin bien structuré sépare généralement deux types de code : les fonctions qui orchestrent WordPress (enregistrement de hooks, requêtes `WP_Query`, écriture en base) et les fonctions qui contiennent la logique pure (calculs, transformations de données, règles métier). Les premières ont besoin d'un environnement WordPress réel pour être testées correctement, avec `WP_UnitTestCase`. Les secondes n'ont besoin que d'isoler les quelques appels WordPress qu'elles font, et Brain Monkey excelle précisément à cela.

Cette séparation, en plus d'accélérer les tests, pousse naturellement vers un code plus découplé : une fonction difficile à tester avec Brain Monkey parce qu'elle mélange trop d'appels WordPress et de logique est souvent une fonction qui gagnerait à être découpée.

## Installer Brain Monkey

Le paquet s'installe via Composer, en dépendance de développement :

```
composer require --dev brain/monkey
```

Il embarque Mockery, la bibliothèque de mocks la plus utilisée en PHP, et fournit une API dédiée aux spécificités de WordPress : hooks, filtres, fonctions globales comme `wp_die()` ou `__()`.

> L'essentiel à retenir : Des tests qui s'exécutent sans base de données ni bootstrap WordPress ; Des hooks et filtres simulés avec Functions\when() ; Une suite jusqu'à dix fois plus rapide sur la logique pure

## Configurer un TestCase dédié

Contrairement à `WP_UnitTestCase`, Brain Monkey s'utilise avec la classe `PHPUnit\Framework\TestCase` standard. Il faut initialiser et nettoyer son environnement dans `setUp()` et `tearDown()` :

```
use Brain\Monkey;
use PHPUnit\Framework\TestCase;

class Test_Calcul_Remise extends TestCase {

    protected function setUp(): void {
        parent::setUp();
        Monkey\setUp();
    }

    protected function tearDown(): void {
        Monkey\tearDown();
        parent::tearDown();
    }
}
```

Beaucoup d'équipes créent une classe abstraite `Brain_Monkey_TestCase` qui centralise ce `setUp()`/`tearDown()`, pour ne pas le répéter dans chaque classe de test.

### Simuler une fonction WordPress avec Functions\when()

Supposons une fonction qui applique une remise et loggue le résultat via `apply_filters()` :

```
function mon_plugin_calcule_remise( $prix, $pourcentage ) {
    $remise = $prix * ( $pourcentage / 100 );
    return apply_filters( 'mon_plugin_remise_calculee', $prix - $remise, $prix, $pourcentage );
}
```

Pour tester cette fonction sans charger WordPress, Brain Monkey permet de définir ce que `apply_filters()` doit retourner :

```
use Brain\Monkey\Functions;

public function test_applique_la_remise_sans_filtre_actif() {
    Functions\when( 'apply_filters' )->returnArg( 1 );

    $resultat = mon_plugin_calcule_remise( 100, 10 );

    $this->assertEquals( 90.0, $resultat );
}
```

`Functions\when()` convient pour les cas simples où l'on veut juste que la fonction WordPress se comporte de façon prévisible. Pour vérifier qu'une fonction WordPress est appelée avec des arguments précis, `Functions\expect()` est plus adapté.

## Vérifier des appels avec Functions\expect()

```
public function test_declenche_le_filtre_avec_les_bons_arguments() {
    Functions\expect( 'apply_filters' )
        ->once()
        ->with( 'mon_plugin_remise_calculee', 90.0, 100, 10 )
        ->andReturn( 90.0 );

    $resultat = mon_plugin_calcule_remise( 100, 10 );

    $this->assertEquals( 90.0, $resultat );
}
```

Ce test échoue si `apply_filters()` n'est pas appelé exactement une fois, avec exactement ces arguments, ce qui en fait un excellent outil pour documenter et verrouiller le contrat d'une fonction.

## Tester hooks et actions

Brain Monkey propose aussi des espaces de noms dédiés aux actions et filtres pour tester qu'une fonction les enregistre correctement :

- `Actions\expectAdded( 'init' )` : vérifie qu'un hook est bien accroché à l'action `init`.
- `Filters\expectApplied( 'the_content' )` : vérifie qu'un filtre donné est bien appliqué.
- `Actions\expectDone( 'save_post' )` : vérifie qu'une action a bien été déclenchée.

```
use Brain\Monkey\Actions;

public function test_enregistre_le_hook_init() {
    Actions\expectAdded( 'init' )->once();

    mon_plugin_enregistrer_hooks();
}
```

## Les limites de l'approche

Brain Monkey ne remplace pas `WP_UnitTestCase` : il ne simule pas la base de données, ne recrée pas d'objets `WP_Post` réels, et ne convient pas pour tester une requête `WP_Query` complète. Utilisé à mauvais escient, il pousse aussi à écrire des tests qui vérifient l'implémentation plutôt que le comportement, en sur-spécifiant chaque appel de fonction.

> Sur nos projets, nous réservons Brain Monkey aux classes de service et aux fonctions de calcul, et nous gardons `WP_UnitTestCase` pour tout ce qui touche réellement à la persistance des données. Mélanger les deux approches dans une même classe de test crée en général plus de confusion que de clarté.

## En résumé

Brain Monkey comble un vide entre les tests unitaires PHP classiques et les tests d'intégration lourds de `WP_UnitTestCase` : il permet d'isoler la logique métier d'un plugin des appels WordPress environnants, avec des suites nettement plus rapides à l'exécution. Combiné avec une architecture qui sépare clairement orchestration et logique pure, c'est l'un des meilleurs investissements pour garder une suite de tests agréable à faire tourner au quotidien.
