✉️

Laravel 11.16 で少し改良されたメールのテストメソッド assertSent を試す

に公開

まえがき

Laravel 11.16 で少し改良されたテスト用メソッドの assertSent を試してみました。

忙しい方のために先に結論を書いてしまいますと、hasTo だけの場合は特別に簡略化させることができ、

    // 今まで
    Mail::assertSent(FooMail::class, function (FooMail $mail) {
        return $mail->hasTo('aaa@example.net');
    });

    // これからはこうも書ける
    Mail::assertSent(FooMail::class, 'aaa@example.net');
    Mail::assertSent(FooMail::class, ['aaa@example.net']); // 又は配列形式で

とこんな感じになります。

本題

という事で、もう少し最初から述べますと、プルリクはこちら Add assertSentTo shorthand #52083。もっとも、プルリクのタイトルからは、assertSentTo が加わったように見えますが、実際は、assertSent が改良されたという事ですね。(assertQueued なども)

では早速、動作確認用の Mailable を下記で作成します。

php artisan make:mail FooMail --view

すると、

   INFO  Mailable [app/Mail/FooMail.php] created successfully.
   INFO  View [resources/views/mail/foo-mail.blade.php] created successfully.

みたいに出力されます。面倒なので、上記2ファイルには手を加えずにそのまま使います。

コントローラ(web.php)は、以下のようにします。

web.php
use App\Mail\FooMail;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Route;

Route::post('/', function (Request $request) {
    $data = $request->validate([
        'email' => ['required', 'email'],
    ]);

    Mail::to($data['email'])->send(new FooMail());

    return view('welcome');
});

email は、本来ならもう少し validation した方が良いですが、今回は取りあえず上記で。

で、上記に対するテストを Pest を使って書いてみます。

use App\Mail\FooMail;
use Illuminate\Support\Facades\Mail;

use function Pest\Laravel\post;

test('メールが送信される', function () {
    Mail::fake();

    post('/', ['email' => 'aaa@example.net'])
        ->assertStatus(200);

    // 以前からあるタイプ
    Mail::assertSent(FooMail::class, function (FooMail $mail) {
        return $mail->hasTo('aaa@example.net');
    });

    // 今回試したいタイプ
    Mail::assertSent(FooMail::class, ['aaa@example.net']);
});

VSCode でテストをサクッと走らせる場合は、筆者が公開している Cute Artisan Test がお勧めですが、それはさておき、上記を実行しますと、無事テストもパスしました 🎉🎉

これでテストコードが少しスッキリ書けますね。
とは言え、hasTo 以外を使う場合は、今まで通りにやる必要があります。

(余談)キューを使ってメールを送信する

ドキュメントを見るか、AI に聞けば普通に分かったりしますが、以下のように変更すれば OK ですね。sendqueue(他にもやり方はあり)

-    Mail::to($data['email'])->send(new FooMail());
+    Mail::to($data['email'])->queue(new FooMail());

(Mailable では、余分な Job とか作る必要はありません)
(もちろん、適宜設定を変更したり、php artisan queue:work なども忘れずに)

キューを使う場合のテストは、assertSent の箇所を assertQueued と書けば OK です。

雑感

ちょっとスッキリ書けるようになったのは、良いことですね🍵
おかしな所がありましたらコメント下さい。

Discussion