確認したこと
LaravelのControllerの中でvalidateメソッドを使用していたので、エラーがblade側で表示されるかテストで確認しようとしてた時の出来事。
validateメソッドの中身はこんな感じ↓↓↓
validate($request, [
...
'user_first_name_kana' => 'required|kana|max:50|',
...
])
ユーザーがカタカナ以外を入力したときにバリデーションで弾かれる処理を書いていました。
これをテストするために、以下のようなテストを書いていたのですが、なぜか通らず。
$response = $this->post(route('hogehoge'), $params);
$response->assertStatus(302);
$response->assertSessionHasErrors('user_first_name_kana');
dd(Session::all())
で、セッション情報を確認。
null
何もないだと…!!!
そもそも、$responseにエラーが返ってきた時の文字が保存されているのかを確認することにした。
$responseの中身をddで、確認してみると…
#messages: array:2 [
"user_first_name_kana" => array:1 []
"user_last_name_kana" => array:1 []
]
$messagesに、何も存在しない。
そんなことはないと思い、Web上の挙動を確認すると、ちゃんとエラーメッセージが表示されていることを確認できた。
テスト側の問題であり、かつsessionにもエラーが保存されていないことまで確認できた。
試したこと
今回、試したことは以下になります。
- WithoutMiddlewareの追加
かなり、沼ってようやく行き着いたのが、WithoutMiddelware
の存在。
というのも、postで呼び出してたエンドポイントが、middlewareで、囲まれていたため、こいつが悪さをしてるようでした。
Route::group(['middleware' => 'not_demo'], function () {
Route::get('hoge', 'hogeController@index');
Route::post('hogehoge', 'hogehogeController@edit');
});
※調べても、具体的な原因には辿り着かず💦
ということで、WithoutMiddlewareのトレイトを使用して、テストコード内のセッション機能を無効にしてみました。
use Illuminate\Foundation\Testing\WithoutMiddleware;
{
use WithoutMiddleware;
...
}
そして、再度ddでレスポンスの中身を確認すると…
#messages: array:2 [
"user_first_name_kana" => array:1 [
0 => "姓(カナ)をカタカナで入力してください"
]
"user_last_name_kana" => array:1 [
0 => "名(カナ)をカタカナで入力してください"
]
]
今度は、ちゃんとmessagesの中身が取得できています!
あとは、assertSessionHasErrorsなどを使用してエラーメッセージがちゃんと表示されることを確認すればテスト終わり!
まとめ
middlewareを使用することによるテストへの影響があることを今回初めて知りました。また、validateメソッドを使用すると自動的にリダイレクトをしたり、その際セッションに一時的にエラーメッセージを保存することも知らなかったので、次からテストを書くときは、一つ一つのメソッドの役割をちゃんと把握しつつ、API側の確認もしっかりしないとなと思いました。