单元测试Laravel的FormRequest

问题描述 投票:18回答:2

我正在尝试单元测试各种自定义FormRequest输入。我找到了解决方案:

  1. 建议使用$this->call(…)方法并使用预期值response断言(link to answer)。这是过度的,因为它直接依赖于路由和控制器。
  2. 泰勒的测试,来自Laravel框架found in tests/Foundation/FoundationFormRequestTest.php。那里有很多嘲弄和开销。

我正在寻找一种解决方案,我可以根据规则对各个字段输入进行单元测试(独立于同一请求中的其他字段)。

SampleRequest示例:

public function rules()
{
    return [
        'first_name' => 'required|between:2,50|alpha',
        'last_name'  => 'required|between:2,50|alpha',
        'email'      => 'required|email|unique:users,email',
        'username'   => 'required|between:6,50|alpha_num|unique:users,username',
        'password'   => 'required|between:8,50|alpha_num|confirmed',
    ];
}

期望的测试:

public function testFirstNameField()
{
   // assertFalse, required
   // ...

   // assertTrue, required
   // ...

   // assertFalse, between
   // ...
}

public function testLastNameField()
{
    // ...
}

我如何单独测试(断言)每个字段的每个验证规则?

php laravel unit-testing request laravel-5.2
2个回答
19
投票

我在Laracast上找到了一个很好的解决方案,并添加了一些定制。

代码

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

/** @test */
public function valid_first_name()
{
    $this->assertTrue($this->validateField('first_name', 'jon'));
    $this->assertTrue($this->validateField('first_name', 'jo'));
    $this->assertFalse($this->validateField('first_name', 'j'));
    $this->assertFalse($this->validateField('first_name', ''));
    $this->assertFalse($this->validateField('first_name', '1'));
    $this->assertFalse($this->validateField('first_name', 'jon1'));
}

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();
}

更新

有一个针对同一问题的e2e方法。您可以将要检查的数据POST到相关路由,然后查看响应是否包含会话错误。

$response = $this->json('POST', 
    '/route_in_question', 
    ['first_name' => 'S']
);
$response->assertSessionHasErrors(['first_name');

-1
投票

朋友们,请进行正确的单元测试,毕竟,不仅是你在这里测试的rulesvalidationDatawithValidator功能也可能存在。

这是应该如何做到的:

<?php

namespace Tests\Unit;

use App\Http\Requests\AddressesRequest;
use App\Models\Country;
use Faker\Factory as FakerFactory;
use Illuminate\Routing\Redirector;
use Illuminate\Validation\ValidationException;
use Tests\TestCase;
use function app;
use function str_random;

class AddressesRequestTest extends TestCase
{


    public function test_AddressesRequest_empty()
    {
        try {
            //app(AddressesRequest::class);
            $request = new AddressesRequest([]);
            $request
                ->setContainer(app())
                ->setRedirector(app(Redirector::class))
                ->validateResolved();
        } catch (ValidationException $ex) {

        }
        //\Log::debug(print_r($ex->errors(), true));

        $this->assertTrue(isset($ex));
        $this->assertTrue(array_key_exists('the_address', $ex->errors()));
        $this->assertTrue(array_key_exists('the_address.billing', $ex->errors()));
    }


    public function test_AddressesRequest_success_billing_only()
    {
        $faker = FakerFactory::create();
        $param = [
            'the_address' => [
                'billing' => [
                    'zip'        => $faker->postcode,
                    'phone'      => $faker->phoneNumber,
                    'country_id' => $faker->numberBetween(1, Country::count()),
                    'state'      => $faker->state,
                    'state_code' => str_random(2),
                    'city'       => $faker->city,
                    'address'    => $faker->buildingNumber . ' ' . $faker->streetName,
                    'suite'      => $faker->secondaryAddress,
                ]
            ]
        ];
        try {
            //app(AddressesRequest::class);
            $request = new AddressesRequest($param);
            $request
                ->setContainer(app())
                ->setRedirector(app(Redirector::class))
                ->validateResolved();
        } catch (ValidationException $ex) {

        }

        $this->assertFalse(isset($ex));
    }


}
© www.soinside.com 2019 - 2024. All rights reserved.