Reputation: 46188
My application sends many emails. The official doc tells how to test emails sending with the HTTP client profiler.
But I obviously don't have a Controller for each email I'm sending.
How can I test my emails that are not triggered from a controller ? (I mean not from a request context).
Further detail on my specific case
I'm using a listener to trigger calls to a service which is doing the "email routing"
What I'd like to do here, is fire some events and check what is sent (the email body, title, recipients, ...)
Upvotes: 3
Views: 508
Reputation: 46188
Following this great post I extended the Swift_MemorySpool
class CountableMemorySpool extends \Swift_MemorySpool implements \Countable
{
public function count()
{
return count($this->messages);
}
public function getMessages()
{
return $this->messages;
}
}
Passed it to the mailer used by my service
class MailServiceTest extends KernelTestCase
{
protected $mailService;
protected $spool;
// ...
protected function setUp()
{
$this->spool = new CountableMemorySpool();
$transport = new \Swift_Transport_SpoolTransport(
new \Swift_Events_SimpleEventDispatcher(),
$this->spool
);
$mailer = new \Swift_Mailer($transport);
$this->mailService->setMailer($mailer);
}
And tested
// ...
public function testMailSpec()
{
// ... Sending the mail ...
$this->assertCount(1, $this->spool,
'Expected exactly one email to be sent');
$msg = $this->spool->getMessages()[0];
$this->assertArrayHasKey('[email protected]', $msg->getTo(),
'Wrong recipient');
$this->assertContains('Tartempion', $msg->getBody(),
'Expected some string contained in the email body');
}
}
Upvotes: 2
Reputation: 3051
First of all, the article you're linking at is about functional (e2e) testing, not the unit.
Second, for unit-testing you need to inject some MailerMocker in your Listener (which sends emails) instead of real Mailer.
For example, you may create a simple Mocker like this
class SwiftMailerTester extends \Swift_Mailer
{
/**
* @var array[\Swift_Mime_Message]
*
*/
protected $sentMessages = array ();
/**
* @var \Swift_Mime_Message
*/
protected $lastSentMessage;
public function __construct() {
}
/**
* Mocks sending message
*
* @param \Swift_Mime_Message $message
* @param null $failedRecepients
*
* @return int
*/
public function send(\Swift_Mime_Message $message, &$failedRecepients = null)
{
$this->lastSentMessage = $message;
$this->sentMessages[] = $message;
return 1;
}
/**
* @return array[\Swift_Mime_Message]
*/
public function getSentMessages()
{
return $this->sentMessages;
}
/**
* @return \Swift_Mime_Message
*/
public function getLastSentMessage()
{
return $this->lastSentMessage;
}
/**
* @return int
*/
public function getSentMessagesCount()
{
return count($this->sentMessages);
}
}
And then in your unit test access lastSentMessage (or sentMessages) to analyze if Listener had done it's work right.
Upvotes: 1
Reputation:
You might want to look into setting up the global request context which, although the documentation is for Commands, should help with your situation unless you can provide further, specific, information.
Upvotes: 0