Return 功能测试中的 Symfony Mailer 电子邮件正文?

Return body of Symfony Mailer email in a functional test?

使用 Mailer,似乎无法在功能测试中检索电子邮件正文。例如,

$email = $this->getMailerMessage(0);
$body = $email->getBody();
var_dump($body);

$body 显示为

object(Symfony\Component\Mime\Part\Multipart\AlternativePart)...

该对象没有(明显的)可访问属性。在功能测试中是否有任何方法可以访问使用 Symfony Mailer 发送的电子邮件正文文本?

使用 SwiftMailer 可以在功能测试中检索电子邮件正文:

$mailCollector = $this->client->getProfile()->getCollector('swiftmailer');
$collectedMessages = $mailCollector->getMessages();
$message = $collectedMessages[0];
$body = $message->getBody();

花了很长时间才找到这个。通过 assertEmailHeaderSame 回溯找到 assertEmailHtmlBodyContains 然后 class EmailHtmlBodyContains 其中有 $message->getHtmlBody().

所以现在我的测试包括 $body = $email->getHtmlBody();,这是一个字符串。哪个可以解析。

那么,让我们开始吧。首先创建你的服务模拟,在你的测试中是这样的:

$this->mailer = $this->createMock(\Swift_Mailer::class);

self::$container->set('swiftmailer.mailer.default', $this->mailer);

在当前测试中为您的消息定义数组变量后

/** @var null|\Swift_Message $emailMessage */
$emailMessages = [];

$this->mailer
    ->method('send')
    ->willReturnCallback(function (\Swift_Message $message) use (&$emailMessages) {
        $emailMessages[] = $message;
    });

因此,我们会将每封电子邮件捕获到 $emailMessages,您只需选择所需的消息并断言其内容,例如:

$emailMessage = $emailMessages[0] ?? null;

$this->assertNotNull($emailMessage);
$this->assertInstanceOf(\Swift_Message::class, $emailMessage);

$body     = $emailMessage->getBody();
$expected = \file_get_contents(__DIR__ . '/../data/RestController/ServiceController/you_message_body.html');
// do not forget to replace dynamic data in the snapshot.
$body     = \preg_replace('/cid:[a-z0-9]{32}/ui', 'cid_here', $body);
$this->assertEquals($expected, $body);
  1. 在您的 services.yaml 附近创建 services_test.yaml 应如下所示:
services:
    # default configuration for services in *this* file
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
        public: true

    test.mailer_symfony: '@Symfony\Component\Mailer\MailerInterface'
  1. 在setup方法中模拟真实服务并在服务容器中更改
use Symfony\Component\Mailer\MailerInterface;

// setUp() 

$this->mailer = $this->createMock(MailerInterface::class);

self::$container->set('test.mailer_symfony', $this->mailer);
  1. 你测试的模拟方法 send(),根据这段代码 https://github.com/symfony/mailer/blob/5.x/MailerInterface.php 它应该是这样的:
use use Symfony\Component\Mime\RawMessage;

// ....

/** @var RawMessage[] $emailMessages */
$emailMessages = [];

$this->mailer
    ->method('send')
    ->willReturnCallback(function (RawMessage $message, Envelope $envelope = null) use (&$emailMessages) {
        $emailMessages[] = $message;
    });

就是这样,您可以在测试结束时断言 $emailMessages,因此,您还可以添加 expects 并检查 send() 方法的调用量