LaravelでHTTPリクエストの単体テストを行う

# 目次
Laravelの記事一覧は下記
[PHPフレームワークLaravelの使い方](https://qiita.com/toontoon/items/c4d0371e504c37f6576e)

# Laravelバージョン
動作確認はLaravel Framework 7.19.1で行っています

# 前提条件
[eclipseでLaravel開発環境を構築する。デバッグでブレークポイントをつけて止める。(WindowsもVagrantもdockerも)](https://qiita.com/toontoon/items/76fa7f8845b20776077c)
本記事は上記が完了している前提で書かれています
プロジェクトの作成もapacheの設定も上記で行っています

[Laravelで入力値エラーチェック(validate)を実装する](https://qiita.com/toontoon/items/abf5c52eb0c3fe11003c)
本記事は上記の内容を理解している前提で書かれています

# フォームリクエストの作成
 /sample/app/Http/Requests/Ut1Request.php作成

```Ut1Request.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class Ut1Request extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'aaaa' => ['max:5']
        ];
    }
}

```
aaaaというリクエストデータにmax:5の制限をかけただけの簡単なエラーチェックです

# Controllerにメソッド追加
(1) /sample/app/Http/Controllers/SampleController.phpに下記を追記
`use App\Http\Requests\Ut1Request;`

(2) /sample/app/Http/Controllers/SampleController.phpにut1メソッドを追記

```
    public function ut1(Ut1Request $request)
    {

        $data = [
            'input_aaaa'   => $request->input('aaaa'),
            'input_bbbb'   => $request->input('bbbb'),
            'session_abcd' => $request->getSession()->get("abcd")
        ];

        return view('sample.ut1', $data);
    }

```

(3) /sample/routes/web.phpに下記を追記
`Route::match(['get', 'post'],'sample/ut1', 'SampleController@ut1');`

# viewの作成
(1) /sample/resources/views/sample/ut1.blade.phpファイル作成

```ut1.blade.php
<html>
    <head>
        <title>sample</title>
    </head>
    <body>

        <form action="{{ url('sample/ut1') }}" method="post">
            @csrf
            @error('a')
                @foreach ($errors->get('aaaa') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>a<input type="text" name="aaaa" value="{{ old('aaaa') }}"></div>

            @error('b')
                @foreach ($errors->get('bbbb') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>b<input type="text" name="bbbb" value="{{ old('bbbb') }}"></div>

            <input type="submit" >
        </form>

        <div>input_a:{{$input_aaaa}}</div>
        <div>input_b:{{$input_bbbb}}</div>
        <div>session_a:{{$session_abcd}}</div>

    </body>
</html>

```

# テストクラス作成
 /sample/tests/Feature/SampleControllerTest.php作成

```SampleControllerTest.php
<?php

namespace Tests\Feature;

use PHPUnit\Framework\TestResult;
use Tests\TestCase;

class SampleControllerTest extends TestCase
{
    public function testUt1()
    {

        // エラーチェック処理テスト
        $response = $this->withSession(
                                      [
                                       'abcd' => 'a_session'
                                      ]
                           )
                         ->post('sample/ut1',
                                [
                                    'aaaa' => '123456',
                                    'bbbb' => 'b_val'
                                ]
                           );
        $response->assertSessionHasErrors(['aaaa' => 'The aaaa may not be greater than 5 characters.']);
        $response->assertStatus(302);

        // 正常系テスト
        $response = $this->withSession([
                                        'abcd' => 'a_session'
                                       ]
                           )
                         ->post('sample/ut1',
                                 [
                                     'aaaa' => 'a_val',
                                     'bbbb' => 'b_val'
                                 ]
                           );
        $response->assertViewHas('input_aaaa', 'a_val');
        $response->assertViewHas('input_bbbb', 'b_val');
        $response->assertViewHas('session_abcd', 'a_session');
        $response->assertStatus(200);

    }

}

```
テストクラスを作成するフォルダはtests/Featureとtests/Unitがありますが、
tests/Unitにはユーティリティクラスなどアプリケーションの一部としてうごく小さな単体テストクラスを格納します
`$this->withSession`はセッションに値を格納します
`$this->withSession`の引数にセッションに格納する値を渡します
`$this->post`はPOSTリクエストを投げるということです
`$this->post`の引数にリクエストデータを渡します
GETリクエストのテストをしたい場合は`$this->get`にします

`$response->assertSessionHasErrors`でエラーメッセージが出力されていることをテストできます
aaaaに対してmax:5のチェックをかけたので、6桁の値をpostリクエストするとエラーになるはずです
`$response->assertViewHas`でviewに渡したデータのテストができます。Controllerでview関数の第二引数に渡した配列の値のテストです
`$response->assertStatus`はHTTPステータスコードのテストです。正常なら200のはずです
他にもいろいろなassertメソッドが用意されています。下記リンクで確認できます
[Laravel 7.x HTTPテスト 利用可能なアサート](https://readouble.com/laravel/7.x/ja/http-tests.html#available-assertions)

# 動作確認
コマンドラインで
`cd sample`
`.\vendor\bin\phpunit tests/Feature/SampleControllerTest.php`
(windowsでない場合./vendor/bin/phpunit)

実行結果

```
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 359 ms, Memory: 20.00 MB

OK (1 test, 7 assertions)
```