Search code examples
symfonymailer

Mailer test fails with Call to a member function getSubject() on null


In a Symfony 5.0.2 project a test of the new Mailer fails with

Error: Call to a member function getSubject() on null

The email service and test are based on symfonycast tutorials.

Adding var_dump($email); in the service immediately after $email = ...; shows object(Symfony\Bridge\Twig\Mime\TemplatedEmail)#24 (11) {..., which says there is a real object created in the service.

services.yaml:

    App\Services\EmailerService:
        $mailer: '@mailer'
        $senderAddress: '%app.sender_address%'

Service:

use Symfony\Bridge\Twig\Mime\TemplatedEmail;

class EmailerService
{
    private $mailer;
    private $sender;

    public function __construct($mailer, $senderAddress)
    {
        $this->mailer = $mailer;
        $this->sender = $senderAddress;
    }

    public function appMailer($mailParams)
    {
        $email = (new TemplatedEmail())
                ->from($this->sender)
                ->to($mailParams['recipient'])
                ->subject($mailParams['subject'])
                ->htmlTemplate($mailParams['view'])
                ->context($mailParams['context']);
        $this->mailer->send($email);
    }
}

Test:

use App\Services\EmailerService;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Mailer\MailerInterface;

class MailerTest extends TestCase
{
    public function testSimpleMessage()
    {
        $symfonyMailer = $this->createMock(MailerInterface::class);
        $symfonyMailer->expects($this->once())
                ->method('send');

        $mailer = new EmailerService($symfonyMailer, '[email protected]', '[email protected]');
        $mailParams = [
            'view' => 'Email/non_user_forgotten_password.html.twig',
            'context' => ['supportEmail' => '[email protected]'],
            'recipient' => '[email protected]',
            'subject' => 'Test message',            
        ];
        $email = $mailer->appMailer($mailParams);

        $this->assertSame('Test message', $email->getSubject());
    }
}


Solution

  • appMailer() must return a TemplatedEmail object so you can call getSubject() on it. Currently it is returning nothing. Change it to:

    public function appMailer($mailParams)
    {
        $email = (new TemplatedEmail())
                ->from($this->sender)
                ->to($mailParams['recipient'])
                ->subject($mailParams['subject'])
                ->htmlTemplate($mailParams['view'])
                ->context($mailParams['context']);
        $this->mailer->send($email);
    
        return $email; // I added this line. 
    }