Как проверить тему письма с помощью laravel's Mailable

Мне интересно, есть ли простой и прямой способ проверить тему письма, используя новую функцию Mailable от Laravel

У меня есть класс, который может отправлять 5 разных писем, но все они одному и тому же человеку, поэтому проверка того, было ли отправлено письмо конкретному человеку, на самом деле не является полным тестом. Мне нужно знать, было ли отправлено конкретное электронное письмо конкретному человеку.

Я думаю, лучше всего использовать тему письма для проверки уникальности. Если у вас есть лучший способ, пожалуйста, скажите мне.

У меня есть это:

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

И я хотел бы добавить что-то вроде этого

Mail::assertSubject('Моя тема', SendEmail::class);

Есть ли способ сделать это??

Спасибо!

1 ответ

редактировать

Быстрое и лучшее решение, чем мое (см. Ниже), можно найти в разделе Как сделать утверждения на 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

В документах о насмешках над почтой вы можете увидеть:

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';
        });

и это должно сработать. Правильно? Ну, это не будет, если вы не сделаете вещи немного по-другому.

ИМО источник ПРОБЛЕМЫ

В руководстве по почте каждый пример, который они представляют, использует build метод:

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

Дело в том, что когда вы звоните Mail::fake() в верхней части вашего метода вы превращаете всю почтовую систему в https://laravel.com/api/5.6/Illuminate/Support/Testing/Fakes/MailFake.html (вот почему она поддерживает assertSent метод среди других), и это подразумевает, что build функция никогда не вызывается.

Решение

Вы должны начать использовать больше __constructor метод класса Mailable. И просто вернуть экземпляр в build() метод:

Следуя (и изменяя) пример просмотра в руководстве по почте:

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 TestCase
{
    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 Работы в модульном тестировании никогда не пройдут в неправильном состоянии.:)

С 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

Надеюсь это поможет!

Примечание: Моя версия 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'
        );
}
Другие вопросы по тегам