Reputation: 4716
With Mailer, it appears not possible to retrieve the body of an email in a functional test. For example, with
$email = $this->getMailerMessage(0);
$body = $email->getBody();
var_dump($body);
$body
is revealed as
object(Symfony\Component\Mime\Part\Multipart\AlternativePart)...
There are no (apparent) accessible properties of that object. Is there any method for accessing the text of the body of an email sent with Symfony Mailer in a functional test?
With SwiftMailer one could retrieve the body of an email in a functional test with:
$mailCollector = $this->client->getProfile()->getCollector('swiftmailer');
$collectedMessages = $mailCollector->getMessages();
$message = $collectedMessages[0];
$body = $message->getBody();
Upvotes: 0
Views: 1459
Reputation: 11
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'
use Symfony\Component\Mailer\MailerInterface;
// setUp()
$this->mailer = $this->createMock(MailerInterface::class);
self::$container->set('test.mailer_symfony', $this->mailer);
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;
});
that's all, you can assert $emailMessages in the end of your test, so, also you can add expects
and check invocations amount of send()
method
Upvotes: 0
Reputation: 11
So, let's start. At first create MOCK of you service, in your test like this:
$this->mailer = $this->createMock(\Swift_Mailer::class);
self::$container->set('swiftmailer.mailer.default', $this->mailer);
after define array variable for your messages in current test
/** @var null|\Swift_Message $emailMessage */
$emailMessages = [];
$this->mailer
->method('send')
->willReturnCallback(function (\Swift_Message $message) use (&$emailMessages) {
$emailMessages[] = $message;
});
so, we will catch each email to $emailMessages, you need just to choose needed message and assert its content like:
$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);
Upvotes: 0
Reputation: 4716
Took quite a while to find this. Backtracked through assertEmailHeaderSame
to find assertEmailHtmlBodyContains
then class EmailHtmlBodyContains
which has $message->getHtmlBody()
.
So now my test includes $body = $email->getHtmlBody();
, which is a string. Which can be parsed.
Upvotes: 2