こんばんは
今回もLaravelネタです。
FormRequestはLaravel使っているうえで結構使うのですが、それのテストって書いてなかったなぁと思ったので、書いてみようと思いました。
本題
まずこんな感じのFormRequest作ります。
UserRegisterRequest.php
<?php namespace App\Requests; use App\Requests\Rules\UserStatusExistsRule; use Illuminate\Foundation\Http\FormRequest; class UserRegisterRequest extends FormRequest { /** * @return bool */ public function authorize(): bool { return true; } /** * @return array */ public function rules(): array { return [ 'name' => 'required|string', 'status' => ['required', 'numeric', new UserStatusExistsRule()], ]; } }
name, status
を リクエストでもらってそれを検証するようなかんたんな形です。
ちなみに、 UserStatusExistsRule
は以下のような形です。
UserStatusExistsRule.php
<?php namespace App\Requests\Rules; use App\Domain\ValueObject\UserStatus; use Illuminate\Contracts\Validation\Rule; class UserStatusExistsRule implements Rule { /** * @param $attribute * @param $value * @return bool */ public function passes($attribute, $value): bool { try { new UserStatus((int)$value)); // 1 or 2でないとExceptionが発生する $result = true; } catch (\Throwable $e) { $result = false; } return $result; } }
これに対してのテストコードは以下
UserRegisterRequestTest.php
<?php namespace Tests\Requests; use App\Requests\UserRegisterRequest; use Illuminate\Routing\Route; use Illuminate\Support\Facades\Validator; use Symfony\Component\HttpFoundation\Request; use Tests\TestCase; class UserRegisterRequestTest extends TestCase { /** * @test * @dataProvider validationDataProvider * @param array $parameters * @param bool $expected * @param string $message * @return void */ public function validation(array $parameters, bool $expected, string $message): void { $request = new UserRegisterRequest(); $validator = Validator::make($parameters, $request->rules(), $request->message()); self::assertSame($expected, $validator->passes(), $message); } /** * @return array */ public function validationDataProvider(): array { return [ [ [], false, 'リクエストが送られていないのでfalse' ], [ ['name' => 'aa'], false, 'statusが送られていないのでfalse' ], [ ['status' => '1'], false, 'nameが送られていないのでfalse' ], [ ['name' => 'ああああ', 'status' => 'ああ'], false, 'statusが数値型ではないのでfalse' ], [ ['name' => 'ああああ', 'status' => '1000'], false, 'statusが許された値ではないのでfalse' ], [ ['name' => 'ああああ', 'status' => '1'], true, '成功パターン' ], ]; } }
作った際のメリットとしては、以下の2点かなと思いました。
- リクエストの全体を網羅的にかんたんにテストできる。
- 上記ができるのでControllerのFeatureテストを薄く出来る。
デメリットは書くのめんどくせーと思うくらいですかね。。。
もっとやりやすいテスト方法あれば教えて下さい!
終わりに
最近やっと本読めるような時間ができてきました。
そういえば、Web+DB Press vol.127 のリファクタリングの話すごくためになりました。
特に凝集度の話勉強になりました。
読んでない方はぜひ