【问题标题】:How to test an email's subject with laravel's Mailable如何使用 laravel Mailable 测试电子邮件的主题
【发布时间】:2017-06-25 23:36:32
【问题描述】:

我想知道,是否有一种简单直接的方法可以使用 Laravel 的新 Mailable 功能来测试电子邮件的主题

我有一个类可以发送 5 封不同的电子邮件,但它们都发送给同一个人,因此测试电子邮件是否发送给具体的人并不是一个完整的测试。我需要知道一封具体的电子邮件是否发送给了具体的人。

我认为,使用电子邮件的主题来测试唯一性是最好的方法。如果你有更好的方法请告诉我。

我有这个:

Mail::assertSentTo([Config::get('mail.backend')], SendEmail::class);

我想添加类似这样的内容

Mail::assertSubject('我的主题', SendEmail::class);

有没有办法做到这一点?

谢谢!

【问题讨论】:

    标签: unit-testing laravel-5 mocking laravel-testing


    【解决方案1】:

    编辑

    比我在How to make assertions on a Laravel Mailable 找到的更快更好的解决方案,感谢@haakym

    在断言之前调用build()方法:

    Mail::assertSent(OrderShipped::class, function ($mail) use ($user) {
                $mail->build();
                return $mail->subject = 'The SUBJECT that I very much need';
            });
    

    我仍然喜欢的任何方式

    Mail::assertSent(InfoRequestMailable::class, function ($mail) {
        $mail->build();
        $this->assertEquals(env('MOREINFO_MAILBOX'), $mail->to[0]['address'], 'The message wasn\'t send to the right email');
        $this->assertEquals('Quite a subject', $mail->subject, 'The subject was not the right one');
        return true;
    });
    
    

    我的原帖

    我看到这个问题已经存在了一段时间,但我偶然发现了同样的问题。

    重要:所有这些都是为了测试一封邮件)。

    使用 Laravel 5.6

    docs about mocking a Mail你可以看到:

    use Illuminate\Support\Facades\Mail;
    
    class ExampleTest extends TestCase
    {
        public function testOrderShipping()
        {
            Mail::fake();
    
            // Perform order shipping...
    
            // Assert a message was sent to the given users...
            Mail::assertSent(OrderShipped::class, function ($mail) use ($user) {
                return $mail->hasTo($user->email) &&
                       $mail->hasCc('...') &&
                       $mail->hasBcc('...');
            });
    
        }
    }
    

    这会简化任何解决方案,对吗?您应该能够执行以下操作:

    
    Mail::assertSent(OrderShipped::class, function ($mail) use ($user) {
                return $mail->subject = 'The SUBJECT that I very much need';
            });
    

    这应该可行。正确的?好吧,除非你做一些不同的事情,否则它不会。

    IMO 问题的根源

    在邮件指南中,他们提出的every example 使用build 方法:

    public function build()
    {
        return $this->from('example@example.com')
                    ->subject('The SUBJECT that I very much need')
                    ->view('emails.orders.shipped');
    }
    

    问题是,当您在方法顶部调用 Mail::fake() 时,您会将整个邮件系统变成 Illuminate\Support\Testing\Fakes\MailFake(这就是它支持 assertSent 方法等的原因),这意味着自定义build 函数永远不会被调用。

    解决方案

    您应该开始更多地在 Mailable 类上使用__constructor 方法。并且只需在 build() 方法中返回实例:

    遵循(并修改)view example in the Mail guide

    namespace App\Mail;
    
    use Illuminate\Mail\Mailable;
    
    class OrderShipped extends Mailable
    {
        ...
    
        /**
         * Create a new message instance.
         *
         * @return void
         */
        public function __construct(Order $order)
        {
            $this->order = $order;
            $this->view('emails.orders.shipped');
            $this->subject('The SUBJECT that I very much need');
        }
    
        /**
         * Build the message.
         *
         * @return $this
         */
        public function build()
        {
            return $this;
        }
    }
    
    

    话虽如此,现在可以了:

    Mail::fake();
    ...
    Mail::assertSent(OrderShipped::class, function ($mail) use ($user) {
                return $mail->subject == 'The SUBJECT that I very much need';
            });
    

    PS

    我宁愿做这样的事情,因为我觉得控制更加精细:

    class MailControllerTest extends oTestCase
    {
        public function testMoreInfo()
        {
            Mail::fake();
    
            // send the mail
    
            Mail::assertSent(InfoRequestMailable::class, function ($mail) {
                $this->assertEquals(env('MOREINFO_MAILBOX'), $mail->to[0]['address'], 'The message wasn\'t send to the right email');
                $this->assertEquals('Quite a subject', $mail->subject, 'The subject was not the right one');
                return true;
            });
        }
    }
    

    assert 在单元测试中的工作方式永远不会出错。 :)

    【讨论】:

    • 你真的在我的项目中帮助了我。谢谢。
    • @TheodoreR.Smith 很高兴为您提供帮助。不要忘记投票。
    【解决方案2】:

    5.4

    要执行您在问题中的测试,您会:

    Mail::assertSent(SendEmail::class, function ($mail) {
        return $mail->hasTo(Config::get('mail.backend'));
    });
    

    要测试您可以执行以下操作的主题:

    Mail::assertSent(SendEmail::class, function ($mail) {
        return $mail->hasTo(Config::get('mail.backend'))
            && $mail->subject == 'My Subject';
    });
    

    https://laravel.com/docs/5.4/mocking#mail-fake

    希望这会有所帮助!

    【讨论】:

    • 您好,谢谢您的回答。显然,MailFake 功能从 5.3 版本到 5.4 版本略有变化。在 5.3 中,我必须这样做: Mail::assertSent(SWIFTListImportFailedEmail::class, function ($mail) { return $mail->emailSubject == 'SWIFT IMPORT FAILED'; }); 然后 Mail::assertSentTo(['test@testemail.com'], SWIFTListImportFailedEmail::class); 谢谢!
    • @FranRoaPrieto 抱歉,我以为你使用的是 5.4。
    • 别担心,当我看到你分享给我的链接时,你给了我线索 谢谢!我看到你评论了我。要评论某人,您只需删除空格?有用吗?:@RossWilson
    【解决方案3】:

    注意:我的 Laravel 版本:6.x

    您需要在断言主题之前调用build() 方法。在这里,我断言电子邮件已发送给经过身份验证的用户,主题是付款存款通知

    Mail::assertQueued(DepositePaymentMail::class, function ($mail) {
        $mail->build();
        return $mail->hasTo(auth()->user()->email) &&
            $mail->subject == 'Payment Deposit Notification';
    });
    

    我的 Mailable 类的构建函数如下所示:

    
    public function build()
    {
        return $this->subject('Payment Deposit Notification')
            ->markdown(
                'email.company.deposite-payment-request'
            );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-16
      • 2021-04-20
      • 2021-06-26
      • 1970-01-01
      • 2014-11-04
      • 2017-10-20
      • 1970-01-01
      • 2020-03-10
      相关资源
      最近更新 更多