✉️
Laravelでメール送信時の属性をアサートする
背景
mocking#mail-fakeにあるように宛先はアサートできるが、その他の属性例えば件名やテンプレートなども同様にアサートしたい。(誰が、誰に、何の件名で、どのテンプレートを使って
メール送信したか)
環境
Laravel: 8.24
内容
一般的なメールに含まれる属性を対象にする。 対象にした属性は以下の通り。
- From
- To
- Subject
- View
以下のような、Mailableクラスを継承したクラスを例に取る。
mail.php
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from('example@example.com')
->markdown('emails.orders.shipped', [
'url' => $this->orderUrl,
])
->subject('example subject');
}
一部抜粋したテストコードは以下の通り。
mailTest.php
<?php
namespace Tests;
use App\Mail\OrderShipped;
use Illuminate\Mail\Markdown;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;
use ReflectionClass;
class ExampleTest extends TestCase
{
public function test_orders_can_be_shipped()
{
Mail::fake();
// Perform sending email
// Assert that a mailable with attributes sent
Mail::assertSent($mailable, function ($mail) use ($data) {
$mail->build();
$reflectionClass = new ReflectionClass($mail);
$reflectionProperty = $reflectionClass->getProperty('markdown');
$reflectionProperty->setAccessible(true);
$view = $reflectionProperty->getValue($mail);
$markdown = $this->app->make(Markdown::class);
$body = $markdown->renderText($view, $mail->buildViewData());
$this->assertSame($mail->viewData, $data['viewData']);
return $mail->hasFrom($data['from'])
$mail->hasTo($data['to']) &&
$mail->subject == $data['subject'] &&
$view == $data['view'] &&
($body) &&
strpos($body, $data['needle']);
}
}
- Mailaleクラスのビューテンプレートはprotectedなプロパティなので、 苦肉の策ではあるが
Reflection
で参照している。 -
markdown
プロパティに指定されているテンプレートの妥当性はneedle
での文字列検索で担保している。(メールのレイアウトやコンテンツの完全一致はテスト観点に含めない) -
viewData
は連想配列形式であり、ユースケースによって項目名が可変するのでassertSame
を使っている。
注意点
-
From
属性をグローバル設定にしている場合は、build()
実行時にはバインドされないのでアサートできないことに注意。
Discussion