問題定義
「メール通知のテストをしたい」「SMS通知(自作Notifier)のテストをしたい」といったとき、
モックを使用すると安全に実行ができ、実行結果の取得も容易にすることができます。
\Illuminate\Support\Facades\Mail::fake();
\Illuminate\Support\Facades\Notification::fake();
ところが、下記のように両方を使用してしまうと、
想定したようにはテストが動きません。
Customer.php
class Customer {
use \Illuminate\Notifications\Notifiable;
public function notify()
{
$this->notify(new MyNotifyInstance($this->notifier));
}
}
CustomerTest.php
class CustomerTest extends TestCase
{
protected function setUp()
{
parent::setUp();
Mail::fake();
Notification::fake();
}
public function testMailNotification()
{
$customer = factory(Customer::class)->create([
'notifier' => 'mail'
]);
$customer->notify();
Mail::assertSent(MyCustomerMail::class, 1); //-> エラー。0件となる
}
public function testSMSNotification()
{
$customer = factory(Customer::class)->create([
'notifier' => 'sms'
]);
$customer->notify();
Notification::assertSentTo( //->OK
[$customerForSMS ], MySMSNotification::class
);
}
}
解決策
CustomerTest.php
class CustomerTest extends TestCase
{
protected function setUp()
{
parent::setUp();
}
public function testMailNotification()
{
Mail::fake(); //個別に設定するよう変更
$customer = factory(Customer::class)->create([
'notifier' => 'mail'
]);
$customer->notify();
Mail::assertSent(MyCustomerMail::class, 1);
}
public function testSMSNotification()
{
Notification::fake(); //個別に設定するよう変更
$customer = factory(Customer::class)->create([
'notifier' => 'sms'
]);
$customer->notify();
Notification::assertSentTo(
[$customer], MySMSNotification::class
);
}
}
原因
Notification::fake() が Mail::fake() を上から潰しているようです。
メール送信処理が発火されず、実行件数が0件となるため、
Mail::fake()を使用する際にはNotification::fake()が実行されないようにします。