search
LoginSignup
2

More than 1 year has passed since last update.

posted at

updated at

Organization

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

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
What you can do with signing up
2