前回のログイン・ログイン失敗のテストに続き、今回はログアウトのテストをご紹介します。また認証機能にBreezeを使用した環境で、ログアウト時のリダイレクト先の変更も行います。

この記事では、Laravel10xにBreezeをインストールした環境でテストを作成しています。テスト環境構築を含む以前の記事は、以下のリンクからご覧いただけます。

ログアウトのテスト

前回と同じくBreezeが提供してくれているテストをベースに、テスト名はそのままでアサーションとポスト送信の記述を少し変更しています。

    public function test_users_can_logout(): void
    {
        $user = User::factory()->create();

        $this->actingAs($user); //$userを認証済み状態に

        $this->assertAuthenticated(); //ログインしていることを確認

        $response = $this->post('/logout');

        $this->assertGuest();         //ログアウトしていることを確認

        $response->assertRedirect('/');
    }

POST送信でログアウトを実行し、正しく認証が削除されているか、リダイレクトされているかをチェックしています。またactingAs()を使うことで、ログイン処理を記述せずに対象のユーザーを認証済み状態に設定できます。

このテストでは分かりやすいようにログアウト動作の前後で認証状態をチェックしていますが、ログアウト前のチェックが不要な場合は以下のように、actingAs()post()を1行で書くこともできます。

        $response = $this->actingAs($user)->post('/logout');

では、テストを実行してみます。

$ php artisan test --filter=test_users_can_logout

   PASS  Tests\Feature\Auth\AuthenticationTest
  ✓ users can logout                                                                                                                   0.63s  

  Tests:    1 passed (4 assertions)
  Duration: 0.93s

問題なさそうですね。

ログアウト後の遷移先を変更(Breeze使用)

デフォルトでログアウト後のリダイレクト先はルート画面となっていますが、異なる画面へ遷移するよう変更したいケースも多いと思います。

Breezeでログアウトの処理がどのように定義されているのか見てみます。まずはルーティングから。

...
    Route::post('logout', [AuthenticatedSessionController::class, 'destroy'])
                ->name('logout');
...

AuthenticatedSessionControllerdestroy()に定義されていることが分かりました。同ファイルを一部抜粋したものが以下になります。

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\LoginRequest;
use App\Providers\RouteServiceProvider;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
use Inertia\Response;

class AuthenticatedSessionController extends Controller
{
...
    /**
     * Destroy an authenticated session.
     */
    public function destroy(Request $request): RedirectResponse
    {
        Auth::guard('web')->logout();

        $request->session()->invalidate();

        $request->session()->regenerateToken();

        return redirect('/');
    }
}

ログアウトの処理と、最後にリダイレクト先が指定されていますね。redirect()の部分を、ログイン画面にリダイレクトするよう修正しました。

        return redirect('/login');

ここで、ログアウトのテストコードに戻ります。

まだテストコードへはリダイレクト先の変更が反映されていないので、テスト失敗が正しい挙動です。念の為テストを実行して確認してみましょう。

$ php artisan test --filter=test_users_can_logout

   FAIL  Tests\Feature\Auth\AuthenticationTest
  ⨯ users can logout                                                                                                                   0.51s  
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────  
   FAILED  Tests\Feature\Auth\AuthenticationTest > users can logout                                                                           
  Failed asserting that two strings are equal.
  -'http://localhost'
  +'http://localhost/login'

ちゃんとリダイレクト先相違のエラーが出ました。コントローラーの変更が反映されていることが分かったので、現在の仕様に合わせてテストを書き換えます。

    public function test_users_can_logout(): void
    {
        $user = User::factory()->create();

        $response = $this->actingAs($user)->post('/logout');

        $this->assertGuest();

        $response->assertRedirect('/login'); //リダイレクト先を修正
    }

テストを実行します。

$ php artisan test --filter=test_users_can_logout

   PASS  Tests\Feature\Auth\AuthenticationTest
  ✓ users can logout                                                                                                                   0.49s  

  Tests:    1 passed (3 assertions)
  Duration: 0.72s

成功しました!次回は、パスワードのリセットに関するテストをご紹介します。

By hmatsu