はじめに
Laravelでテストコードを実装していた時、ルーティングを間違えたせいでコントローラにアクセスできず、しばらくブロックされていました。
基本的な所ではありますが、自戒も込めて対応法をまとめておきます。
環境
Laravel 9.52.16
問題
- 問題となったテストコード
SalesOrdersControllerTest.php(一部略)
public function test_sales_destroy(): void
{
// テスト用のユーザを作成
$user = User::factory()->create();
$formData = [
'category_id' => 1,
// 以下略
];
// フォームデータを保存
$response = $this->actingAs($user)->post('/my/sales/store', $formData);
$sales_order = $user->sales_orders()->first();
$response = $this->actingAs($user)->delete('/my/sales/destroy/' . $sales_order->id);
$response->assertStatus(302);
$this->assertDatabaseMissing('sales_orders', [
'user_id' => $user->id,
]);
}
- エラーの内容
root:/var/www/html/niches # php artisan test --filter test_sales_destroy
FAIL Tests\Feature\SalesOrdersControllerTest
⨯ sales destroy
---
Tests\Feature\SalesOrdersControllerTest > sales destroy
Expected response status code [302] but received 404.
Failed asserting that 302 is identical to 404.
「Httpステータスコードはお求めの302リダイレクトじゃなくて、404NotFoundを返してるぞ」と仰っています。
参考までに、web.php内のルーティングは次のようになっています。
web.php(一部略)
Route::delete('sales/destroy/{saleId}', [SalesOrdersController::class, 'destroy'])->name('sales-destroy');
解決法
- テスト内のdeleteメソッドが存在しないルーティングにアクセスしようとしていました
SalesOrdersControllerTest.php(失敗)
$response = $this->actingAs($user)->delete('/my/sales/destroy/' . $sales_order->id);
destroyアクションへのルーティングはweb.php内で「sales/destroy/{saleId}」となっているので…
SalesOrdersControllerTest.php(解決)
$response = $this->actingAs($user)->delete('/sales/destroy/' . $sales_order->id);
こちらが正しいですね!
まとめ
ググってみた感じ、404エラーの原因のほとんどがルーティングに関係してそうです。
今後404エラーが出た際には、ルーティングを正しく書いているかどうか、という所から確認したいと思います。