Search code examples
symfonyfunctional-testingswiftmailer

How to test email in functional test (Symfony2)


I'm trying to test email in functional test...

My source code is the same as the example of the cookbook,

the controller :

public function sendEmailAction($name)
{
    $message = \Swift_Message::newInstance()
        ->setSubject('Hello Email')
        ->setFrom('[email protected]')
        ->setTo('[email protected]')
        ->setBody('You should see me from the profiler!')
    ;

    $this->get('mailer')->send($message);

    return $this->render(...);
}

And the test :

// src/Acme/DemoBundle/Tests/Controller/MailControllerTest.php
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class MailControllerTest extends WebTestCase
{
    public function testMailIsSentAndContentIsOk()
    {
        $client = static::createClient();

        // Enable the profiler for the next request (it does nothing if the profiler is not available)
        $client->enableProfiler();

        $crawler = $client->request('POST', '/path/to/above/action');

        $mailCollector = $client->getProfile()->getCollector('swiftmailer');

        // Check that an e-mail was sent
        $this->assertEquals(1, $mailCollector->getMessageCount());

        $collectedMessages = $mailCollector->getMessages();
        $message = $collectedMessages[0];

        // Asserting e-mail data
        $this->assertInstanceOf('Swift_Message', $message);
        $this->assertEquals('Hello Email', $message->getSubject());
        $this->assertEquals('[email protected]', key($message->getFrom()));
        $this->assertEquals('[email protected]', key($message->getTo()));
        $this->assertEquals(
            'You should see me from the profiler!',
            $message->getBody()
        );
    }
}

however I got this error :

PHP Fatal error: Call to a member function getCollector() on a non-object

The problem comes from this line :

$mailCollector = $client->getProfile()->getCollector('swiftmailer');

any idea ?


Solution

  • The exception is being thrown because getProfile() returns false if the profiler is not enabled. see here.

    public function getProfile()
    {
        if (!$this->kernel->getContainer()->has('profiler')) {
            return false;
        }
    
        return $this->kernel->getContainer()->get('profiler')->loadProfileFromResponse($this->response);
    }
    

    Furthermore enableProfiler()only enables the profiler if it is registered with the service-container aka enabled. see here.

    public function enableProfiler()
    {
        if ($this->kernel->getContainer()->has('profiler')) {
            $this->profiler = true;
        }
    }
    

    Now you have to make sure the profiler is enabled in the test environment. ( should normally be the default setting )

    config_test.yml

    framework:
       profiler:
           enabled: true
    

    You could add something like this to your test:

    $this->assertEquals($this->kernel->getContainer()->has('profiler'), true);