wp_remote_post() qui retourne un WP_Error, ou pire, une réponse HTTP 503 avec un corps HTML de page de maintenance HubSpot : c’est le scénario qu’un connecteur d’extension doit absolument prévoir, et que la majorité des suites de tests ignorent purement et simplement.
Le connecteur en question synchronisait les inscriptions d’un formulaire de contact vers une liste HubSpot, à chaque soumission. Tant que l’API répondait, tout fonctionnait. Le jour où HubSpot a connu une panne partielle de quelques minutes, chaque soumission de formulaire s’est traduite par une erreur 500 côté site, visible par les visiteurs, alors que le seul problème venait d’un service tiers totalement indépendant du site lui-même.
Simuler la panne sans dépendre du vrai service
Le principe reste le même que pour tout appel API externe testé en local : intercepter la requête sortante via le filtre pre_http_request et renvoyer une réponse fabriquée qui imite la panne, sans jamais toucher au réseau.
add_filter('pre_http_request', function ($preempt, $args, $url) {
if (str_contains($url, 'api.hubapi.com')) {
return new WP_Error(
'http_request_failed',
'Connexion à HubSpot impossible (simulation de test).'
);
}
return $preempt;
}, 10, 3);
Vérifier la dégradation, pas seulement l’absence de crash
Un test qui se contente de vérifier que le code ne lève pas d’exception est insuffisant : il faut vérifier ce que fait réellement le connecteur en cas d’échec.

class SynchronisationHubspotTest extends WP_UnitTestCase
{
public function test_une_panne_hubspot_met_la_soumission_en_file_dattente(): void
{
$this->simuler_panne_hubspot();
$connecteur = new HubspotConnecteur();
$resultat = $connecteur->synchroniser([
'email' => 'test@example.test',
'prenom' => 'Camille',
]);
$this->assertTrue($resultat->est_en_attente());
$this->assertCount(1, get_option('hubspot_file_attente', []));
}
}
Ce test-là garantit deux choses en une seule assertion réaliste : la soumission n’est pas perdue, et l’appelant (souvent un contrôleur de formulaire) reçoit une réponse qui ne ressemble pas à une erreur fatale.
Le message affiché ne doit jamais exposer la panne technique
Autre point souvent oublié : que voit l’internaute qui remplit le formulaire pendant la panne ? Le test doit aussi couvrir le rendu du message de confirmation.
- Le formulaire doit afficher un message de succès générique, jamais le contenu brut du
WP_Error. - Un journal d’erreurs interne (via
error_logou un logger dédié) doit conserver la trace technique pour l’équipe support. - Une tâche planifiée (
wp_schedule_event) doit reprendre la file d’attente dès que l’API redevient disponible, sans double envoi.
Couvrir le rejeu et la reprise après panne
Une fois la panne simulée et absorbée, il reste à vérifier la reprise : la file d’attente doit se vider proprement quand HubSpot répond à nouveau, sans dupliquer les contacts déjà synchronisés avant l’incident.
public function test_la_reprise_vide_la_file_sans_doublon(): void
{
update_option('hubspot_file_attente', [
['email' => 'deja-en-attente@example.test'],
]);
$this->simuler_hubspot_disponible();
(new HubspotConnecteur())->traiter_file_attente();
$this->assertEmpty(get_option('hubspot_file_attente', []));
}
Un connecteur CRM n’est robuste que le jour où l’on a testé sa panne, pas son fonctionnement nominal : c’est dans l’échec que se joue la confiance du client final.
En résumé
Simuler une panne HubSpot ne demande ni compte de test ni accès réseau : le filtre pre_http_request suffit à fabriquer n’importe quel scénario d’échec, du timeout au 503. Ce qui compte ensuite, c’est de vérifier trois choses précises — la mise en file d’attente, le message affiché à l’internaute, et la reprise sans doublon — plutôt que de se contenter d’un test qui prouve seulement l’absence de crash immédiat.