LoginSignup
2

More than 3 years have passed since last update.

Laravel で FromRequest のバリデーションをテストする

Last updated at Posted at 2020-07-06

Laravel の FormRequest クラスを利用すると各フィールドのバリデーションルールを array の形で定義することができます。

<?php

namespace App\Http\Requests\UserRegistration;

use Illuminate\Foundation\Http\FormRequest;

class UserRegistrationFormRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name' => [
                'required',
                'string',
                'min:2',
                'regex:/^[A-Za-z0-9]+$/',
            ],
            'password' => [
                'required',
                'string',
                'min:8',
                'regex:/[a-z]/',
                'regex:/[A-Z]/',
                'regex:/[0-9]/',
                'regex:/@$!%*#?&/',
            ],
        ];
    }
}

一つ一つのルールをテストするメリットは特にないと思いますが、上記のような複数ルールの組み合わせやカスタムバリデーションを検証するために Unit Test を作成する際の Tips を紹介します。

テストコード

ベースとなるメソッドは Stack Overflow から拝借しています(というか、この記事の要点はこの方法の紹介です!)。
これをベースに汎用的な FormRequest 用の TestCase クラスを作ってみます。

<?php

namespace Tests\Unit\App\Requests\Base;

use Illuminate\Foundation\Testing\TestCase;

abstract class BaseFormRequestTestCase extends TestCase
{
    /**
     * @var array
     */
    protected $rules;
    /**
     * @var \Validator
     */
    protected $validator;

    public function setUp(): void
    {
        parent::setUp();
        $this->setRules();
        $this->validator = $this->app['validator'];
    }

    /**
     * 子クラスで Request Class が持つ rules を set する。
     */
    abstract protected function setRules(): void;

    protected function getFieldValidator($field, $value)
    {
        return $this->validator->make(
            [$field => $value],
            [$field => $this->rules[$field]]
        );
    }

    protected function validateField($field, $value)
    {
        return $this->getFieldValidator($field, $value)->passes();
    }
}

これを継承した形で TestCase を作成すれば比較的シンプルにバリデーションのテストを書くことができます。

<?php

namespace Tests\Unit\App\Requests\UserRegistration\UserRegistrationFormRequest;

use App\Http\Requests\UserRegistration\UserRegistrationFormRequest;
use Tests\Unit\App\Requests\Base\BaseFormRequestTestCase;

class UserRegistrationFormRequestTest extends BaseFormRequestTestCase
{
    protected function setRules(): void
    {
        $this->rules = (new UserRegistrationFormRequest())->rules();
    }

    public function testNameRules() {
        $this->assertFalse($this->validateField('name', null));
        $this->assertFalse($this->validateField('name', 'a'));
        $this->assertTrue($this->validateField('name', 'ab'));
        $this->assertTrue($this->validateField('name', 'AB'));
        $this->assertTrue($this->validateField('name', '01'));
        $this->assertTrue($this->validateField('name', 'aA0'));
        $this->assertFalse($this->validateField('name', 'ab@'));
        $this->assertFalse($this->validateField('name', 'ab cd'));
    }

    public function testPasswordRules() {
        $this->assertFalse($this->validateField('password', null));
        $this->assertFalse($this->validateField('password', 'abAB01@'));
        $this->assertTrue($this->validateField('password', 'abAB01@$'));
        $this->assertFalse($this->validateField('password', 'abcABC012'));
        $this->assertFalse($this->validateField('password', 'ABC012@$!'));
        $this->assertFalse($this->validateField('password', '012@$!abc'));
        $this->assertFalse($this->validateField('password', '@$!abcABC'));
        $this->assertFalse($this->validateField('password', 'ab AB 01 @$'));
    }
}

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
2