Вернуть тело письма Symfony Mailer в функциональном тесте?

#symfony #symfony-mailer

#симфония #symfony-почтовая программа

Вопрос:

С помощью Mailer, по-видимому, невозможно получить текст сообщения электронной почты в ходе функционального теста. Например, с помощью

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

$body раскрывается как

объект(SymfonyComponentMimePartMultipartAlternativePart)…

У этого объекта нет (очевидных) доступных свойств. Существует ли какой-либо способ доступа к тексту тела электронного письма, отправленного с помощью Symfony Mailer в функциональном тестировании?

С помощью SwiftMailer можно получить текст электронного письма в функциональном тестировании с помощью:

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

Ответ №1:

Потребовалось довольно много времени, чтобы найти это. Проследил assertEmailHeaderSame назад , чтобы найти assertEmailHtmlBodyContains то class EmailHtmlBodyContains , что есть $message->getHtmlBody() .

Итак, теперь мой тест включает $body = $email->getHtmlBody(); в себя, который является строкой. Которые могут быть проанализированы.

Ответ №2:

Итак, давайте начнем. Сначала создайте МАКЕТ вашего сервиса в вашем тесте следующим образом:

 $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 (amp;$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. Я рекомендую создавать все макеты в методе setUp(), вот почему я использую свойство для МАКЕТА

2. Спасибо за ваш вклад. Пожалуйста, обратите внимание, что вопрос (и ответ) относится к Symfony Mailer, а не к SwiftMailer.

3. тот же метод, разница только в обслуживании

4. То, что вы описываете, не является функциональным тестом из-за использования MOCK .

5. это МАКЕТ в функциональном тесте, вы можете установить МАКЕТ в контейнер Symfony вместо реального сервиса. Все будет работать как обычно, но этот сервис будет МАКЕТНЫМ. Вы когда-нибудь пытались это сделать? Итак, давайте попробуем!

Ответ №3:

  1. Создайте services_test.yaml рядом с вашими сервисами.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: '@SymfonyComponentMailerMailerInterface'
 
  1. В методе установки имитируйте реальную службу и измените ее в сервисном контейнере
 use SymfonyComponentMailerMailerInterface;

// 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 SymfonyComponentMimeRawMessage;

// ....

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

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

вот и все, вы можете указать $emailMessages в конце вашего теста, таким образом, вы также можете добавлять expects и проверять количество вызовов send() метода