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 @$'));
}
}