Laravel 单元测试邮件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25222570/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 09:55:33  来源:igfitidea点击:

Laravel unit testing emails

phplaravellaravel-4

提问by T3chn0crat

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 to check that?

我知道您可以将其置于假装模式并记录在日志中。有什么可以检查的吗?

回答by Laurence

There are two options.

有两种选择。

Option 1 - Mock the mail facade to test the mail is being sent. Something like this would work:

选项 1 - 模拟邮件外观以测试正在发送的邮件。像这样的事情会起作用:

$mock = Mockery::mock('Swift_Mailer');
$this->app['mailer']->setSwiftMailer($mock);
$mock->shouldReceive('send')->once()
    ->andReturnUsing(function($msg) {
        $this->assertEquals('My subject', $msg->getSubject());
        $this->assertEquals('[email protected]', $msg->getTo());
        $this->assertContains('Some string', $msg->getBody());
    });

Option 2 is much easier - it is to test the actual SMTP using MailCatcher.me. Basically you can send SMTP emails, and 'test' the email that is actuallysent. Laracasts has a great lesson on how to use it as part of your Laravel testing here.

选项 2 更容易 - 它是使用MailCatcher.me测试实际的 SMTP 。基本上,您可以发送 SMTP 电子邮件,并“测试”实际发送的电子邮件。Laracasts 有一个关于如何在 Laravel 测试中使用它的重要课程

回答by Slava V

For Laravel 5.4 check Mail::fake(): https://laravel.com/docs/5.4/mocking#mail-fake

对于 Laravel 5.4 检查Mail::fake()https: //laravel.com/docs/5.4/mocking#mail-fake

回答by happy_marmoset

"Option 1" from "@The Shift Exchange" is not working in Laravel 5.1, so here is modified version using Proxied Partial Mock:

“@The Shift Exchange”中的“Option 1”在 Laravel 5.1 中不起作用,所以这里是使用 Proxied Partial Mock 的修改版本:

$mock = \Mockery::mock($this->app['mailer']->getSwiftMailer());
$this->app['mailer']->setSwiftMailer($mock);
$mock
    ->shouldReceive('send')
    ->withArgs([\Mockery::on(function($message)
    {
        $this->assertEquals('My subject', $message->getSubject());
        $this->assertSame(['[email protected]' => null], $message->getTo());
        $this->assertContains('Some string', $message->getBody());
        return true;
    }), \Mockery::any()])
    ->once();

回答by Thiago Mata

If you just don't want the e-mails be really send, you can turn off them using the "Mail::pretend(true)"

如果您只是不想真正发送电子邮件,则可以使用“Mail::pretend(true)”关闭它们

class TestCase extends Illuminate\Foundation\Testing\TestCase {
    private function prepareForTests() {
      // e-mail will look like will be send but it is just pretending
      Mail::pretend(true);
      // if you want to test the routes
      Route::enableFilters();
    }
}

class MyTest extends TestCase {
    public function testEmail() {
      // be happy
    }
}

回答by Sevenearths

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

如果有人使用 docker 作为开发环境,我最终会通过以下方式解决这个问题:

Setup

设置

.env

.env

...
MAIL_FROM       = [email protected]

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

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

docker-compose.ymal

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

app/Http/Controllers/SomeController.php

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('[email protected]')->send(new SomeMail('Body of the email'));
        ...
    }

app/Mail/SomeMail.php

app/Mail/SomeMail.php

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class SomeMail extends Mailable
{
    use Queueable, SerializesModels;

    public $body;

    public function __construct($body = 'Default message')
    {
        $this->body = $body;
    }

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

resources/views/mail/SomeMail.blade.php

resources/views/mail/SomeMail.blade.php

<h1>{{ $body }}</h1>

Testing

测试

tests\Feature\EmailTest.php

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('[email protected]', 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)

(来源:https: //stackoverflow.com/a/52177526/563247

回答by Antoine Augusti

I think that inspecting the log is not the good way to go.

我认为检查日志不是好方法。

You may want to take a look at how you can mock the Mail facade and check that it receives a call with some parameters.

您可能想看看如何模拟 Mail 外观并检查它是否收到带有一些参数的调用。