Laravel unit testing emails

前端 未结 8 1576
难免孤独
难免孤独 2021-02-20 10:12

My system sends a couple of important emails. What is the best way to unit test that?

I see you can put it in pretend mode and it goes in the log. Is there something t

8条回答
  •  星月不相逢
    2021-02-20 10:44

    If any one is using docker as there development environment I end up solving this by:

    Setup

    .env

    ...
    MAIL_FROM       = noreply@example.com
    
    MAIL_DRIVER     = smtp
    MAIL_HOST       = mail
    EMAIL_PORT      = 1025
    MAIL_URL_PORT   = 1080
    MAIL_USERNAME   = null
    MAIL_PASSWORD   = null
    MAIL_ENCRYPTION = null
    

    config/mail.php

    # update ...
    
    'port' => env('MAIL_PORT', 587),
    
    # to ...
    
    'port' => env('EMAIL_PORT', 587),
    

    (I had a conflict with this environment variable for some reason)

    Carrying on...

    docker-compose.ymal

    mail:
        image: schickling/mailcatcher
        ports:
            - 1080:1080
    

    app/Http/Controllers/SomeController.php

    use App\Mail\SomeMail;
    use Illuminate\Http\Request;
    use Illuminate\Routing\Controller as BaseController;
    
    
    class SomeController extends BaseController
    {
        ...
        public function getSomething(Request $request)
        {
            ...
            Mail::to('someone@example.com')->send(new SomeMail('Body of the email'));
            ...
        }
    

    app/Mail/SomeMail.php

    body = $body;
        }
    
        public function build()
        {
            return $this
                ->from(ENV('MAIL_FROM'))
                ->subject('Some Subject')
                ->view('mail.someMail');
        }
    }
    

    resources/views/mail/SomeMail.blade.php

    {{ $body }}

    Testing

    tests\Feature\EmailTest.php

    use Tests\TestCase;
    use Illuminate\Http\Request;
    use App\Http\Controllers\SomeController;
    
    class EmailTest extends TestCase
    {
        privete $someController;
        private $requestMock;
    
        public function setUp()
        {
            $this->someController = new SomeController();
            $this->requestMock = \Mockery::mock(Request::class);
        }
    
        public function testEmailGetsSentSuccess()
        {
            $this->deleteAllEmailMessages();
    
            $emails = app()->make('swift.transport')->driver()->messages();
            $this->assertEmpty($emails);
    
            $response = $this->someController->getSomething($this->requestMock);
    
            $emails = app()->make('swift.transport')->driver()->messages();
            $this->assertNotEmpty($emails);
    
            $this->assertContains('Some Subject', $emails[0]->getSubject());
            $this->assertEquals('someone@example.com', array_keys($emails[0]->getTo())[0]);
        }
    
        ...
    
        private function deleteAllEmailMessages()
        {
            $mailcatcher = new Client(['base_uri' => config('mailtester.url')]);
            $mailcatcher->delete('/messages');
        }
    }
    

    (This has been copied and edited from my own code so might not work first time)

    (source: https://stackoverflow.com/a/52177526/563247)

提交回复
热议问题