例。ユーザー削除時に連携するサービスも削除するイベント
実際に書いたコードから少し内容を変えており、実際に動かない可能性がありますことを最初にお断りします。エッセンスを伝えるためのコードとなります。
例えば、ログインに外部の OpenId Connect サービスを使う場合、今回は Google としましょうか。ユーザーを作成したときは Laravel の googles テーブルに連携時のデータを保存しているものとし、モデルでは user->google
でアクセスできるものとします。
ユーザーを削除する時にイベントを実行し、リスナーで Laravel の google レコードを削除するとします。この時のリスナーの handle メソッドを、次のようにテストしました。
- ポイント。リスナーのテストのコツと言っても、リスナークラスをインスタンスかして handle メソッドを実行するだけ。アサートは実行した結果を確かめる。
- おまけポイント。 イベントリスナー DeleteGoogle クラスはコンストラクタで DI を行っている。この DI を自動的に行って欲しいので
app
メソッドを使用した。 - おまけポイント。テストメソッド内でも、
app
メソッドは普通に使える。 - おまけポイント。ファクトリの
states
メソッドで users レコード作成後に googles レコードも作成している。登録は、UserFactory
クラスでafterCreating
メソッドを使って行っている。
use RefreshDatabase;
public function setUp(): void
{
parent::setUp();
$this->seed();
}
/**
* @test
*
* @return void
*/
public function ユーザー連携するGoogleアカウントレコードが削除されること(): void
{
$user = factory(User::class)->states('withGoogle')->create();
$google = $user->google;
Http::fake([
'accounts.google.com/*' => Http::response(null, 204),
]);
$listner = app(DeleteGoogle::class);
$listenr->handle(new UserDleting($user));
$this->asertDeleted($google);
}
おわりに
イベントを使えば、例えばコントローラのアクションで一番行うべきロジックでは無いけれどもこのアクションで済ませておくべきロジックを分離するのに適していると感じます。
うまく分離できていれば、コントローラーのアクションのユニットテストにはイベントが発生したことの確認を追加するだけでよく、イベントのリスナーで実行される内容は別のユニットテストに切り出すことができます。
しかし、コントローラーのアクションのテストの方法は公式ドキュメントで記述されていますけれども、イベントのリスナーメソッドのユニットテスト方法は見当たりませんでした。
そこで、自分なりに調べて落ちついた方法を今回ノートいたしました。
以上です。