You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MailHog测试邮件发送 assertEmailCount断言失败问题

MailHog测试时assertEmailCount断言计数为0的问题处理

问题复现

测试邮件发送逻辑时,两种断言写法均无法捕获发送至MailHog的邮件:

// 两种写法均不生效
$this->assertEmailCount(1, 'smtp://mailhog:1025');
$this->assertEmailCount(1);

对应返回错误:

Failed asserting that the Transport smtp://mailhog:1025 has sent "1" emails (0 sent).
Failed asserting that the Transport has sent "1" emails (0 sent).

实际邮件发送逻辑正常,每次运行测试都能在MailHog后台看到对应邮件,手动封装的Mailer实例获取代码如下:

private function getMailer(array $mailConfig): MailerInterface
{
    $dsn = match (strtolower($mailConfig['transport'])) {
        'sendgrid' => 'smtp://mailhog:1025',
        'mailchimp' => 'smtp://mailhog:1025',
        default => 'smtp://mailhog:1025'
    };

    $transport = Transport::fromDsn($dsn);

    return new Mailer($transport);
}

根本原因

assertEmailCount这类邮件断言,依赖框架测试容器中注入的、带发送行为埋点追踪能力的Mailer/Transport实例实现计数。
当前手动调用Transport::fromDsn()创建传输实例、再手动new出Mailer对象的写法,完全绕开了框架的测试追踪链路,断言自然统计不到这个手动实例发出的邮件,才会返回发送数为0的结果。
邮件能正常送达MailHog仅代表手动创建的实例SMTP配置正确,和断言的计数链路完全独立,和MailHog本身的配置没有关系。

修复方案

  • 不要在业务或测试代码中手动实例化Transport和Mailer对象,直接通过依赖注入从容器获取MailerInterface实例,测试环境下框架会自动为该实例挂载追踪逻辑,断言可正常统计发送行为。
  • 在测试环境配置文件(.env.test)中统一配置MailHog的DSN即可,不需要在代码内硬编码DSN做分支判断:
    MAILER_DSN=smtp://mailhog:1025
    
  • 如果业务确实需要动态切换发信配置,也要通过容器修改Mailer实例的配置项,不能手动new实例,否则所有邮件相关断言都会失效。
  • MailHog本身无特殊测试配置要求,只要服务1025端口可正常连通收信即可满足测试需求。

内容的提问来源于stack exchange,提问作者Toma Tomov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 13:27:18