Note de terrain · Tutoriels

Tests d’e-mails Laravel 13 en 2026 : Mail::fake peut-il prouver la livraison ?

Vous testez des e-mails de validation, de réinitialisation ou de notification avec Laravel 13 ? Nous distinguons les preuves fournies par les assertions applicatives, l’inspection des Mailables et la réception réelle, puis proposons une méthode de choix adaptée à chaque objectif.

Le test annonce que le courriel de réinitialisation est envoyé, mais aucune boîte de réception ne le montre.

La solution la plus rapide : avec Mail::fake, vérifiez l’appel d’envoi, le destinataire et le contenu attendu ; pour prouver une réception externe, ajoutez un essai avec une adresse de test contrôlée. Les tests d’e-mails Laravel 13 ne constituent pas une preuve unique : chaque couche valide une étape différente.

Cet article s’adresse aux développeurs qui vérifient une inscription ou une réinitialisation de mot de passe, aux équipes QA qui définissent des critères de régression et aux indépendants qui contrôlent leurs courriels en préproduction sans les envoyer à de vrais utilisateurs. Il ne s’agit pas d’un guide de configuration du transport, mais d’une manière de choisir les preuves qui correspondent à votre critère d’acceptation.

Trois preuves distinctes, trois limites à garder en tête

Nous séparons le parcours du courriel en trois affirmations vérifiables. Cette distinction évite de transformer une réussite locale en promesse de réception.

Niveau de preuve Ce que le test permet d’affirmer Ce qu’il ne démontre pas
Appel de l’application Le code a demandé l’envoi du Mailable attendu ou sa mise en file Que le transport a été exécuté ou que le destinataire a reçu le message
Contenu du Mailable Les éléments préparés par l’application correspondent aux attentes du test Le rendu final dans tous les clients de messagerie ou la livraison externe
Réception contrôlée Une adresse de test a reçu un message lors de cet essai Une délivrabilité générale, future ou garantie pour chaque fournisseur

Cette grille résume une limite importante : « l’application a appelé l’envoi » n’équivaut pas à « le message est arrivé ». La documentation Laravel 13 décrit les tests avec Mail::fake, les assertions d’envoi et de mise en file ainsi que l’examen des Mailables ; elle ne présente pas ces assertions comme une preuve de réception par une boîte externe (documentation Laravel sur les tests de courrier).

En pratique, un test vert peut coexister avec un mauvais destinataire, un contenu incomplet, un traitement de file qui n’a pas été exécuté ou un refus du côté du service destinataire. Ce ne sont pas des contradictions : les tests observent des étapes différentes. Nous nommons donc explicitement, dans le code et dans le compte rendu QA, la couche réellement validée.

Appel d’envoi : ce que Mail::fake valide

Mail::fake permet d’empêcher l’envoi réel pendant un test et de vérifier le comportement de l’application. Le test peut notamment affirmer qu’un Mailable attendu a été envoyé, qu’un autre ne l’a pas été, ou qu’un message a été mis en file. Les méthodes décrites par Laravel incluent, entre autres, assertSent, assertNotSent, assertQueued et assertNotQueued (référence de l’API MailFake).

Voici un exemple simplifié, à adapter aux classes de votre propre application :

use Illuminate\Support\Facades\Mail;

public function test_registration_sends_verification_email(): void
{
    Mail::fake();

    $response = $this->post('/register', [
        'name' => 'Camille Test',
        'email' => 'qa@example.test',
        'password' => 'test-password',
        'password_confirmation' => 'test-password',
    ]);

    $response->assertRedirect();

    Mail::assertSent(VerifyEmail::class, function (VerifyEmail $mail) {
        return $mail->hasTo('qa@example.test');
    });
}

Dans cet exemple, l’assertion soutient une conclusion précise : le scénario d’inscription a demandé l’envoi de VerifyEmail pour le destinataire indiqué. Elle ne prouve pas que le message a quitté l’application. Le transport est précisément remplacé par le faux utilisé dans le test.

Cette limite est utile, pas gênante. Elle rend les tests applicatifs reproductibles et évite qu’une suite de tests envoie des messages accidentels à des personnes réelles. Elle permet aussi de tester les branches métier : après une inscription valide, l’application doit demander un courriel ; en cas d’échec de validation, elle ne doit pas en demander. En revanche, elle ne répond pas à la question « un fournisseur externe l’a-t-il accepté ? ».

Nous évitons aussi de lire une assertion trop largement. Si le test vérifie seulement qu’un Mailable a été envoyé, il ne prouve ni le bon lien de validation ni le bon destinataire, sauf si ces éléments sont contrôlés séparément. Si le test filtre le destinataire, il ne prouve pas pour autant que le message a été reçu par cette adresse.

Pour vérifier les choix d’adresse utilisés dans un parcours de test, vous pouvez compléter cette méthode par notre guide du choix d’une adresse de réception de test. Le choix de l’adresse est une décision de test ; il ne remplace pas l’assertion sur le comportement de l’application.

Contenu préparé : contrôler les Laravel Mailables

La deuxième couche porte sur le Mailable lui-même. Un appel d’envoi peut être déclenché correctement alors que le sujet, le destinataire, le texte ou le lien généré est erroné. Nous testons donc le contenu indépendamment de la question du transport.

Laravel fournit des méthodes d’assertion pour examiner des éléments du Mailable, notamment l’expéditeur, les destinataires, le sujet et le contenu. Les noms et comportements exacts doivent être vérifiés dans la documentation et l’API de la version concernée ; le guide Laravel 13 détaille les vérifications de contenu, et l’index API expose les assertions associées aux Mailables (documentation des tests de courrier ; index des assertions Mailable).

Contrôle sur le Mailable Exemple de question de test Portée de la conclusion
Destinataire L’adresse correspond-elle au compte qui vient de s’inscrire ? Le Mailable est préparé pour la bonne adresse
Sujet et expéditeur Le sujet est-il celui attendu et l’expéditeur correctement défini ? Les champs contrôlés correspondent aux attentes
Corps et lien Le texte contient-il l’instruction prévue et le lien attendu ? Le contenu préparé contient les éléments vérifiés
Rendu reçu Le message reste-t-il lisible dans le client ciblé ? Nécessite une inspection ou un essai de réception complémentaire

Pour un courriel de réinitialisation, nous vérifions par exemple que l’instruction attendue figure dans le corps et que le lien correspond au scénario testé. Pour une notification de facture, nous contrôlons plutôt l’identité du destinataire, les informations essentielles et la présence des éléments métier attendus. Dans les deux cas, il faut tester des éléments stables et utiles au comportement ; vérifier chaque détail de mise en forme dans un test unitaire rend souvent la suite fragile sans améliorer la preuve de livraison.

Un Mailable peut également être correct dans sa structure et se présenter différemment une fois interprété par un client de messagerie. Les retours à la ligne, les styles, les images et les liens méritent une vérification visuelle lorsque leur affichage fait partie du critère d’acceptation. Cela concerne aussi les campagnes de démonstration audio ou vidéo et les courriels créés pour présenter un portfolio ou un travail de design : la cohérence du rendu compte alors autant que la présence du texte dans l’objet PHP.

Une assertion de contenu valide l’objet contrôlé par Laravel. Elle ne simule pas tous les logiciels de messagerie et ne mesure pas le placement dans la boîte de réception.

Mise en file : distinguer le travail prévu du travail exécuté

Un Mailable envoyé immédiatement et un Mailable mis en file ne correspondent pas à la même étape. Dans le second cas, l’application demande généralement qu’un travail soit traité ultérieurement. Une réponse HTTP réussie peut donc attester que le parcours web s’est terminé comme prévu sans démontrer que le travailleur a ensuite pris en charge le message.

La documentation Laravel distingue les assertions d’envoi et de mise en file. assertSent correspond à l’affirmation « l’application a envoyé ce Mailable dans le scénario testé » ; assertQueued correspond à « l’application a placé ce Mailable en file ». Si le code doit mettre le Mailable en file, l’assertion doit suivre ce choix, plutôt que de traiter les deux mécanismes comme interchangeables (documentation officielle des files Laravel 13 ; référence de l’API QueueFake).

Comportement attendu Assertion à privilégier Ce que la vérification ne couvre pas
Le scénario demande un envoi non mis en file assertSent L’acceptation par le transport et la réception externe
Le scénario met le Mailable en file assertQueued L’exécution ultérieure par un travailleur
Le scénario ne doit envoyer aucun courriel assertNotSent Les autres effets possibles en dehors du faux utilisé
Le scénario ne doit pas mettre le courriel en file assertNotQueued Une éventuelle réception, qui n’est pas le but de cette assertion

Ces méthodes sont des vérifications du faux, pas des sondes de transport. Pour un parcours asynchrone, nous documentons séparément l’événement que le test contrôle : demande de mise en file, exécution du travail, appel du transport ou réception observée. Sans cette précision, un rapport de test peut donner l’impression que toute la chaîne a été vérifiée alors que seule la première étape l’a été.

FAQ : choisir l’assertion selon l’étape réellement testée

Mail::fake confirme-t-il une réception externe ?

Non. Mail::fake remplace le transport dans le test et observe les demandes d’envoi ou de mise en file faites par l’application. Il est donc adapté aux tests de logique métier, mais ne contacte pas une boîte externe pour prouver la réception. Pour cette preuve, il faut réaliser un essai séparé avec une adresse contrôlée et observer le message effectivement reçu.

Faut-il choisir assertSent ou assertQueued ?

Utilisez assertSent si le scénario doit appeler l’envoi sans mise en file. Choisissez assertQueued si le Mailable est destiné à être placé dans une file. Une assertion de mise en file ne démontre pas que le travailleur a exécuté le travail ; un test d’exécution ou un contrôle complémentaire est nécessaire si cette étape fait partie de l’acceptation.

Comment examiner les destinataires et le contenu d’un Laravel Mailable ?

Contrôlez les champs utiles avec les assertions documentées pour votre version de Laravel : destinataires, expéditeur, sujet et éléments du corps. Séparez ce test de l’assertion qui vérifie l’appel d’envoi, afin de savoir précisément ce qui a échoué. Ces contrôles portent sur le Mailable construit par votre application, pas sur son affichage universel dans les clients de messagerie.

Quand faut-il vérifier le courriel dans une vraie boîte ?

Faites-le lorsque le critère inclut le parcours externe : le transport doit être configuré, un message doit parvenir à une adresse de test, et ses liens et son contenu doivent être inspectables. La réception confirme uniquement le résultat de cet essai dans cet environnement. Elle ne garantit pas que les prochains messages seront acceptés ou placés en boîte principale.

Réception externe : preuve locale et boîte réelle ne se confondent pas

Un outil de capture local est précieux pour inspecter un message généré sans l’envoyer à un véritable destinataire. Il aide à lire le contenu produit et à vérifier les liens lors du développement. Mais le message capturé dans un environnement local n’a pas nécessairement traversé le même transport que celui de préproduction ou de production. Il ne prouve donc pas, à lui seul, qu’une boîte externe l’a reçu.

Lorsque le critère porte sur la réception réelle, nous ajoutons un essai contrôlé : déclencher le parcours autorisé, vérifier que l’adresse de test est bien le destinataire, observer l’arrivée du message et contrôler que le contenu et les liens sont utilisables. Si la préproduction peut envoyer des courriels, nous isolons les comptes et les adresses de test afin de ne pas exposer des utilisateurs réels à des notifications non sollicitées.

L’inspection doit rester proportionnée au risque. Pour une simple notification interne de démonstration, une vérification de contenu et un contrôle périodique du transport peuvent suffire. Pour une inscription, un lien de validation inutilisable bloque le parcours ; la réception contrôlée devient alors une preuve pertinente avant mise en production. Pour un courriel de réinitialisation, nous vérifions aussi que le lien conduit au bon environnement et ne révèle pas de données de compte dans le message.

Un résultat positif ne doit pas être généralisé. Il signifie que, dans cet essai, avec cette adresse et cet environnement, le message a été observé. Il ne garantit pas que toutes les boîtes le traiteront de la même façon, que le message évitera les indésirables ou que la configuration restera correcte après un changement de transport. Pour structurer cette observation, le guide de réception et d’arrivée des codes par courriel peut aider à distinguer le délai observé, le contenu et le résultat visible, sans transformer un seul essai en garantie globale.

Décider quelles preuves ajouter à votre suite

Nous choisissons les tests à partir du critère d’acceptation, plutôt qu’en ajoutant systématiquement une réception réelle à chaque cas unitaire. Cela maintient une suite rapide pour la logique métier tout en réservant les contrôles externes aux parcours où ils apportent une preuve supplémentaire.

  • Si le critère est que l’inscription demande un courriel au bon destinataire, choisissez Mail::fake et une assertion d’envoi portant sur le Mailable et l’adresse attendus.
  • Si le critère inclut le sujet, le contenu ou le lien produit, conservez l’assertion d’envoi et ajoutez des vérifications spécifiques du Mailable.
  • Si le Mailable doit être traité de manière asynchrone, vérifiez sa mise en file avec l’assertion correspondante ; si l’exécution du travailleur est aussi exigée, testez cette étape séparément.
  • Si le critère exige une réception hors de l’application, ajoutez un essai avec une boîte de réception de test contrôlée et vérifiez le message arrivé.
  • Si le scénario touche des comptes réels, des paiements ou des communications sensibles, n’utilisez pas une boîte temporaire comme unique moyen de récupération ; prévoyez une adresse durable et un parcours de test explicitement autorisé.

Cette décision évite deux excès. Le premier consiste à croire qu’un test applicatif prouve toute la chaîne. Le second consiste à dépendre d’une boîte réelle pour vérifier chaque branche métier, au prix d’une suite plus fragile et d’un risque d’envoi involontaire. Pour les comptes de préproduction, le contrôle des données et de la confidentialité des inscriptions aide à réfléchir à la séparation entre données de test et coordonnées personnelles.

Une procédure de validation lisible par l’équipe

Pour rendre les résultats exploitables par les développeurs et la QA, nous formulons chaque contrôle comme une affirmation vérifiable. Le compte rendu peut suivre une séquence simple, sans confondre les étapes :

  1. Définir l’événement métier : inscription, réinitialisation ou notification, dans un environnement de test autorisé.
  2. Choisir la preuve attendue : appel d’envoi, contenu du Mailable, mise en file, exécution du travail ou réception externe.
  3. Écrire l’assertion de l’application : vérifier le type de Mailable, le destinataire et le comportement conditionnel pertinent.
  4. Examiner le contenu : contrôler le sujet, le corps et les liens indispensables au parcours.
  5. Contrôler la file si nécessaire : préciser si le test valide la mise en file ou également le traitement ultérieur.
  6. Réaliser un essai externe uniquement si le critère l’exige : utiliser une adresse contrôlée, puis vérifier le message reçu.
  7. Rapporter la portée du résultat : écrire « Mailable mis en file » ou « message reçu dans l’adresse de test », plutôt que « livraison garantie ».

Ces étapes sont volontairement séparées. Un test qui passe à l’étape d’assertion métier ne doit pas être présenté comme une validation du fournisseur de courrier. Un essai de réception réussit pour le message observé, mais n’exonère pas de vérifier le Mailable dans les tests automatisés. En nommant la preuve, l’équipe sait quelle régression le test détecte et quelle question reste ouverte.

Choisir une boîte de test sans promettre davantage que l’essai

Pour un contrôle externe, une adresse dédiée évite d’utiliser la boîte personnelle d’un développeur ou celle d’un collègue. Elle réduit aussi le risque de mêler courriels de préproduction et conversations professionnelles. L’adresse doit être accessible pendant l’essai, adaptée au scénario et exclue des envois destinés aux utilisateurs réels.

Une boîte temporaire peut convenir à un essai ponctuel de réception ou à la vérification d’un lien de validation, à condition de vérifier ses modalités d’accès avant le test. Elle ne remplace pas une adresse durable pour un compte qui doit être récupéré à long terme, ni une adresse capable de répondre lorsque le scénario exige un échange. Pour comparer les types d’adresses selon le besoin, tenez compte de la durée d’accès requise, de la possibilité de répondre et des contraintes de récupération ; ne présumez pas que toutes les solutions couvrent les mêmes usages.

FwdTmp peut être envisagé comme une option de réception distincte lorsque le test doit observer un message hors de l’application. Vérifiez sur le service les modalités actuellement proposées avant d’en faire une dépendance de préproduction : une adresse de test facilite l’isolation, mais ne garantit ni l’arrivée de chaque courriel ni la qualité de délivrabilité de votre application. Pour les tests d’appel et de contenu, gardez Mail::fake et les assertions Laravel au centre de la suite ; réservez la boîte de réception au contrôle que ces tests ne peuvent pas apporter.

Questions fréquentes

Mail::fake confirme-t-il qu’un message a été reçu dans une boîte externe ?

Non. Mail::fake remplace le transport pendant le test et permet de vérifier que l’application a demandé l’envoi d’un Mailable, ou sa mise en file. Cela valide le comportement du code dans ce périmètre, pas la transmission par un fournisseur, l’acceptation par le serveur destinataire ni l’arrivée dans la boîte de réception.

Comment choisir entre assertSent et assertQueued dans un test Laravel ?

Choisissez assertSent lorsque le scénario doit appeler l’envoi sans mise en file. Si le Mailable implémente ShouldQueue et que votre comportement attendu est sa mise en file, vérifiez plutôt assertQueued. L’assertion doit correspondre à l’étape que vous souhaitez contrôler : elle ne prouve pas, à elle seule, que le travailleur a exécuté le travail.

Comment contrôler le destinataire et le contenu d’un Laravel Mailable ?

Testez séparément le Mailable pour examiner ses destinataires, son expéditeur, son sujet et son contenu attendu, selon les assertions disponibles dans la documentation Laravel 13. Ces vérifications portent sur l’objet produit par l’application. Elles ne garantissent ni le rendu identique dans tous les logiciels de messagerie ni la réception par un serveur externe.

Dans quels cas faut-il tester avec une vraie boîte de réception ?

Ajoutez une réception contrôlée lorsque l’acceptation porte sur le parcours complet : transport configuré, message effectivement reçu, lien utilisable et contenu lisible dans le client visé. Cet essai complète les tests automatisés ; un résultat positif reste limité à l’adresse, à l’environnement et au moment observés, sans garantir toutes les livraisons futures.

Commencez par moins exposer vos données

Pour votre prochaine inscription, commencez par une boîte de réception vierge.