Symfony 3.4 PHPUnit测试中如何正确访问私有SwiftMailer服务?
解决Symfony中SwiftMailer私有服务的弃用警告问题
这个问题我之前也踩过坑,Symfony 3.2+把swiftmailer.mailer标记为私有服务,就是为了引导大家用更规范的依赖注入方式,而不是直接从容器里捞服务。直接获取私有服务的做法在Symfony 4.0+会直接报错,所以得换正确的姿势:
为什么会出现这个警告?
Symfony从3.2版本开始,将大部分核心服务设置为私有,目的是避免开发者直接从容器中获取服务,而是通过构造函数注入的方式使用服务,这样能让代码的依赖关系更清晰,也更符合依赖注入的设计原则。直接调用$container->get('swiftmailer.mailer')获取私有服务,就会触发这个弃用警告。
正确的解决方案(推荐两种)
方案一:在测试中通过容器安全获取私有服务(适合简单测试)
如果你的测试类继承自KernelTestCase或者WebTestCase,在测试环境下其实可以合法获取私有服务,只需要保持bootKernel()的调用,然后直接从容器中获取即可(Symfony在测试环境默认允许获取私有服务):
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Swift_Mailer; class MailerServiceTest extends KernelTestCase { private $swiftMailer; protected function setUp(): void { // 启动Kernel,初始化容器 self::bootKernel(); // 直接获取私有服务,测试环境下是允许的 $this->swiftMailer = self::$container->get('swiftmailer.mailer'); } public function testEmailSending() { // 这里写你的测试逻辑,比如调用邮件服务发送邮件 // $this->swiftMailer->send(...); } }
方案二:用内存邮件池测试邮件内容(更专业的测试方式)
如果你的目的是验证邮件是否正确发送、内容是否符合预期,更推荐用SwiftMailer的内存邮件池,这样不需要实际发送邮件,就能捕获所有待发送的邮件进行验证:
- 首先配置测试环境的SwiftMailer
在config/packages/test/swiftmailer.yaml中添加以下配置,让测试环境使用内存邮件池:
swiftmailer: transport: null # 禁用实际传输 spool: { type: memory } # 使用内存保存待发送邮件
- 在测试中捕获并验证邮件
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Swift_MemorySpool; class MailerServiceTest extends KernelTestCase { public function testSendEmail() { self::bootKernel(); // 获取你的邮件服务(推荐用依赖注入,而不是直接捞容器) $mailService = self::$container->get(YourCustomMailService::class); // 调用发送邮件的方法 $mailService->sendWelcomeEmail('user@example.com'); // 获取SwiftMailer实例 $mailer = self::$container->get('swiftmailer.mailer'); // 获取内存邮件池 $spool = $mailer->getTransport()->getSpool(); // 确保邮件池是内存类型 $this->assertInstanceOf(Swift_MemorySpool::class, $spool); // 从邮件池取出所有待发送的邮件 $messages = $spool->flushQueue(new \Swift_Transport_NullTransport($mailer)); // 验证邮件数量 $this->assertCount(1, $messages); // 验证邮件的收件人、主题、内容 $sentMessage = $messages[0]; $this->assertEquals(['user@example.com' => null], $sentMessage->getTo()); $this->assertEquals('欢迎注册', $sentMessage->getSubject()); $this->assertStringContainsString('感谢您注册我们的平台', $sentMessage->getBody()); } }
不推荐的方案:将服务设为公共
虽然可以通过配置把swiftmailer.mailer设为公共服务,但这违背了Symfony的设计原则,不建议长期使用:
在config/services.yaml的测试环境配置中添加:
when@test: services: swiftmailer.mailer: public: true
总结
优先用方案二,既能解决弃用警告,又能更全面地测试邮件发送的逻辑;如果只是简单测试邮件服务的可用性,方案一也足够。
内容的提问来源于stack exchange,提问作者eldiablo62
相关产品推荐
相关产品推荐

