0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Expected response status code [201] but received 404.Failed asserting that 201 is identical to 404.

Posted at

開発環境

  • Mac OS Monterey(バージョン12.2.1)
  • MacBook Air (M1)
  • composer version 2.0.9
  • Laravel Framework 10.10
  • phpunit 10.1

HTTPリクエストのテストコードを実装したので、以下のコマンドを実行。

php artisan test tests/Feature/APITest.php

すると、以下のようなエラーが!!!

Expected response status code [201] but received 404.
Failed asserting that 201 is identical to 404.

201のステータスコードを期待したが、404を受け取っているらしい。

中々苦戦したが、下記を試すことによりテストを通すことができたのでよかったら参考にしてください。

※ちなみに今回は、テストコード用のDBを作成していないので、localを使用しています。

今回使用したコード

Route::middleware(['middleware' => 'web'])->group(function () {
    //todo作成
    Route::get('/todos', [PostController::class, 'create']);
    Route::post('/todos', [PostController::class, 'create']);
...
});
class APITest extends TestCase
{
    public function test_HTTPリクエスト()
    {
				$response = $this->postJson('/web/todos');
        $response->assertCreated();
    }
}

試したこと

今回試したこととしては、以下になります。

  • エラー内容の確認をして、RouteServiceProvider.phpの中身を変更
  • VerifyCsrfToken.phpのファイルの書き換え

エラー内容の確認をして、RouteServiceProvider.phpの中身を変更

とりあえず、以下のエラーを再確認。

Expected response status code [201] but received 404.Failed asserting that 201 is identical to 404.     

     21     // }
     22     public function test_トップ()
     23     {
     24         $response = $this->postJson('/web/todos');
    25         $response->assertCreated();
     26     }
     27 }
     28 
     29 // class ControllerTest extends TestCase

エラー箇所を確認していて、1つ思ったのが、PostControllerではRoute::get('/todos')としているのに、テストコードの中では、/web/todosとしている点。

webをつけていた理由としては、RouteServiceProvider.phpのmidleware(’web’)の定義のprefixで、webを指定していたのでつけていたのだが、postControllerの中では/todosとしているので、とりあえず、prefixを削除。

public function boot(): void
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
        });

        $this->routes(function () {
            Route::middleware('api')
                ->namespace($this->namespace)
                ->prefix('api')
                ->group(base_path('routes/api.php'));

            Route::middleware('web')
                ->namespace($this->namespace)
                ->prefix('web')//←これを削除
                ->group(base_path('routes/web.php'));
        });
    }

また、テストコードの中も、/todosとした。

再度php artisan test tests/Feature/APITest.phpのコマンドを実行したところ…

Expected response status code [200] but received 419.
Failed asserting that 200 is identical to 419.

エラーが変わった!!!

VerifyCsrfToken.phpのファイルの書き換え

このエラーを調べるとどうやらセッションエラーらしく、エラー内容確認のため以下をテストコードに追加。

class APITest extends TestCase
{
    public function test_HTTPリクエスト()
    {
				$this->withoutExceptionHandling();//←追加
				$response = $this->postJson('/todos');
        $response->assertCreated();
    }
}

CSRFが一致していないというエラーであることがわかった。

CSRF token mismatch.

postController上でmiddlewareを使用していることからCSRFの機能が提供されているので、テストコード上では無効にしたい。

そこで、ファイルの内容を以下のように変更。

...
public function handle($request, \Closure $next)
    {
        if (env('APP_ENV') !== 'local') {//←この部分はAPP_ENVに合わせる
            return parent::handle($request, $next);
        }

        return $next($request);
    }

ちなみに、公式ドキュメントにもCSRFは無効にしようの文言がありました。

Tip!! 利便性を良くするため、テストの実行時にCSRFミドルウェアを自動で無効にします。

HTTPテスト 10.x Laravel

再度php artisan test tests/Feature/APITest.phpのコマンドを実行

Expected response status code [201] but received 200.
Failed asserting that 201 is identical to 200.

おお、エラーの内容がまた変わった!

そして、200番台になっているので、サーバー側のエラーは無くなったと思われる。

APITestの中身を確認し、assertCreated()を調べてみる。

class APITest extends TestCase
{
    public function test_HTTPリクエスト()
    {
				$this->withoutExceptionHandling();//←追加
				$response = $this->postJson('/todos');
        $response->assertCreated();//←ここを変更
    }
}

どうやら、assertCreatedは201を返すらしく、ここでは200を使用したいのでassertOkに変更。

これでようやく…

PASS  Tests\Feature\APITest
   HTTPリクエスト                                                                                                                                              0.12s  

  Tests:    1 passed (1 assertions)
  Duration: 0.18s

テストコードが通りました〜

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?