カテゴリー
コンピューター

Laravel 6 。ファイルを扱うシンプルな CRUD API の例、その2。バリデーションとそのテストを作った。

はじめに

Laravel 6 。ファイルを扱うシンプルな CRUD API の例を作った (今後 Dropzon.js を試すために) – oki2a24 の続きで、バリデーションとそのテストを作りました。

コード。フォームリクエストクラスとそのテスト

フォームリクエストクラスの laravel/app/Http/Requests/Api/FileStoreRequest.php です。 バリデーションルールは次としました。

  • required 。今回の例では、ファイル以外の項目はリクエストボディに存在しないため、必須としました。ファイルの添付がオプションである場合は nullalbe にするなど適宜変更となると思います。
  • imagefile では広すぎで、 mimetypesmimes では面倒と感じましたので image としました。
  • max:2000 。最大 2000 キロバイト、つまりほぼ 2 メガバイトとしました。
<?php

namespace App\Http\Requests\Api;

use Illuminate\Foundation\Http\FormRequest;

class FileStoreRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'file' => 'required|image|max:2000',
        ];
    }
}

フォームリクエストクラスのテストクラスの laravel/tests/Feature/FileStoreRequestTest.php です。 テスト用のダミーファイルについては、 ファイルアップロードのテスト – HTTPテスト 6.x Laravel を参考にしました。

<?php

namespace Tests\Feature;

use App\Http\Requests\Api\FileStoreRequest;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Tests\TestCase;

class FileStoreRequestTest extends TestCase
{
    /**
     * @test
     * @return void
     */
    public function 必須エラーとなること()
    {
        // 準備
        $data = [
            'file' => null,
        ];

        // 実行
        $validator = Validator::make($data, (new FileStoreRequest())->rules());

        // 確認。成否
        $this->assertTrue($validator->fails());
        // 確認。失敗内容
        $this->assertEquals([
            'file' => ['Required' => [],],
        ], $validator->failed());
    }

    /**
     * @test
     * @return void
     */
    public function ファイルが画像ではない時にエラーとなること()
    {
        // 準備
        Storage::fake();
        $file = UploadedFile::fake()->create('document.pdf');
        $data = [
            'file' => $file,
        ];

        // 実行
        $validator = Validator::make($data, (new FileStoreRequest())->rules());

        // 確認。成否
        $this->assertTrue($validator->fails());
        // 確認。失敗内容
        $this->assertEquals([
            'file' => ['Image' => [],],
        ], $validator->failed());
    }

    /**
     * @test
     * @return void
     */
    public function 最大サイズエラーとなること()
    {
        // 準備
        Storage::fake();
        $file = UploadedFile::fake()->image('document.jpg')->size(2001);
        $data = [
            'file' => $file,
        ];

        // 実行
        $validator = Validator::make($data, (new FileStoreRequest())->rules());

        // 確認。成否
        $this->assertTrue($validator->fails());
        // 確認。失敗内容
        $this->assertEquals([
            'file' => ['Max' => [2000],],
        ], $validator->failed());
    }
}

コード。その他。

フォームリクエストクラスを使うようにしたコントローラクラスの laravel/app/Http/Controllers/Api/FileController.php です。差分のみを示します。 アクションの引数をフォームリクエストクラスに変更するだけです。コントローラのテストクラスも、成功時のパターンの観点でのみのテストですのでコントローラのテストクラスの変更の必要はありません。もしエラーのパターンもコントローラのテストで行っている場合は、おそらく変更が必要となると思います。

$ git diff laravel/app/Http/Controllers/Api/FileController.php
diff --git a/laravel/app/Http/Controllers/Api/FileController.php b/laravel/app/Http/Controllers/Api/FileController.php
index 5564da7..e98da0e 100644
--- a/laravel/app/Http/Controllers/Api/FileController.php
+++ b/laravel/app/Http/Controllers/Api/FileController.php
@@ -3,10 +3,10 @@
 namespace App\Http\Controllers\Api;

 use App\Http\Controllers\Controller;
+use App\Http\Requests\Api\FileStoreRequest;
 use App\Http\Resources\File as FileResource;
 use App\Models\File;
 use Illuminate\Http\JsonResponse;
-use Illuminate\Http\Request;
 use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
 use Illuminate\Http\Response;
 use Illuminate\Support\Facades\Storage;
@@ -26,10 +26,10 @@ class FileController extends Controller
     /**
      * Store a newly created resource in storage.
      *
-     * @param  \Illuminate\Http\Request  $request
+     * @param  FileStoreRequest  $request
      * @return FileResource
      */
-    public function store(Request $request): FileResource
+    public function store(FileStoreRequest $request): FileResource
     {
         $file = $request->file('file');
         $path = $file->store('files');
@@ -56,11 +56,11 @@ class FileController extends Controller
     /**
      * Update the specified resource in storage.
      *
-     * @param  \Illuminate\Http\Request  $request
+     * @param  FileStoreRequest  $request
      * @param  File  $file
      * @return FileResource
      */
-    public function update(Request $request, File $file): FileResource
+    public function update(FileStoreRequest $request, File $file): FileResource
     {
         $filePathToBeDeleted = $file->path;
$

おわりに

ファイルアップロードは文字列を POST するのと勝手が異なりますので、バリデーションする時も少しもたついてしまいます。わかってしまえば、または思い出してしまえば、どうってことはありませんので、そのきっかけとするために、今回投稿いたしました。

以上です。

コメントを残す