Shopware 6开发:测试环境下如何绕过限制发送真实邮件?
Shopware 6 测试环境发送真实邮件的解决方法
场景说明
我们在Shopware 6开发过程中使用单元/集成测试,已经通过禁用DatabaseTransactionBehaviour保留测试数据,方便在管理后台查看调试。现在需要在仅开发调试阶段的测试中发送真实邮件(CI环境不启用),已在.env.test配置了有效的MAILER_URL,但测试时邮件无法发出——这是因为Shopware 6测试环境默认拦截了邮件发送。
解决方案
Shopware 6测试环境默认使用NullTransport丢弃所有邮件,我们可以通过动态替换邮件传输服务的方式绕过限制,以下是具体实现:
方法1:在单个测试类中启用真实邮件
在需要发送真实邮件的测试类的setUp方法中,动态替换邮件传输配置,同时通过环境变量控制是否启用,避免影响CI:
protected function setUp(): void { parent::setUp(); // 仅当测试环境、开启调试且设置SEND_REAL_MAILS=1时启用 if ($this->getContainer()->getParameter('kernel.environment') === 'test' && getenv('APP_DEBUG') === '1' && getenv('SEND_REAL_MAILS') === '1') { $mailerDsn = \Symfony\Component\Mailer\Transport\Dsn::fromString(getenv('MAILER_URL')); // 创建真实的邮件传输实例 $transport = (new \Symfony\Component\Mailer\Transport\DsnTransportFactory())->create($mailerDsn); // 替换容器中的邮件传输服务 $this->getContainer()->set('mailer.transport', $transport); } }
然后在.env.test中添加开关:
SEND_REAL_MAILS=1 MAILER_URL=smtp://x:y@smtp.mailtrap.io:2525?encryption=tls&auth_mode=login
方法2:创建可复用的测试Trait
如果多个测试类需要这个功能,可以封装成Trait,方便复用:
trait RealMailTestBehaviour { protected function setUp(): void { parent::setUp(); // 通过环境变量控制是否启用真实邮件发送 if (getenv('SEND_REAL_MAILS') !== '1') { return; } $mailerDsn = \Symfony\Component\Mailer\Transport\Dsn::fromString(getenv('MAILER_URL')); $transport = (new \Symfony\Component\Mailer\Transport\DsnTransportFactory())->create($mailerDsn); $this->getContainer()->set('mailer.transport', $transport); } }
在测试类中使用这个Trait:
class MyMailTest extends KernelTestCase { use IntegrationTestBehaviour; use RealMailTestBehaviour; // 测试代码... }
注意事项
- 务必只在开发调试阶段启用,CI环境下要设置
SEND_REAL_MAILS=0,避免发送冗余邮件或泄露测试数据 - 不要直接修改全局的
config/packages/test/mailer.yaml配置,以免影响所有测试用例
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

