单元测试 Laravel 的 FormRequest
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36978147/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unit Test Laravel's FormRequest
提问by Dov Benyomin Sohacheski
I am trying to unit test various custom FormRequest
inputs. I found solutions that:
我正在尝试对各种自定义FormRequest
输入进行单元测试。我找到了以下解决方案:
Suggest using the
$this->call(…)
method and assert theresponse
with the expected value (link to answer). This is overkill, because it creates a direct dependency on Routingand Controllers.Taylor's test, from the Laravel Frameworkfound in
tests/Foundation/FoundationFormRequestTest.php
. There is a lot of mocking and overhead done there.
建议使用该
$this->call(…)
方法并response
使用预期值断言(链接到答案)。这有点矫枉过正,因为它直接依赖Routing和Controllers。Taylor 的测试,来自Laravel Framework中的
tests/Foundation/FoundationFormRequestTest.php
. 那里有很多嘲笑和开销。
I am looking for a solution where I can unit test individual field inputs against the rules (independent of other fields in the same request).
我正在寻找一种解决方案,我可以在其中根据规则对各个字段输入进行单元测试(独立于同一请求中的其他字段)。
Sample FormRequest:
样本表格请求:
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',
];
}
Desired Test:
所需测试:
public function testFirstNameField()
{
// assertFalse, required
// ...
// assertTrue, required
// ...
// assertFalse, between
// ...
}
public function testLastNameField()
{
// ...
}
How can I unit test (assert)each validation rule of every field in isolation and individually?
如何单独和单独地对每个字段的每个验证规则进行单元测试(断言)?
回答by Dov Benyomin Sohacheski
I found a good solution on Laracastand added some customization to the mix.
我在Laracast上找到了一个很好的解决方案,并在混合中添加了一些自定义。
The Code
编码
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();
}
Update
更新
There is an e2eapproach to the same problem. You can POSTthe data to be checked to the route in question and then see if the response contains session errors.
有一种e2e方法可以解决同样的问题。您可以将要检查的数据POST到有问题的路由,然后查看响应是否包含会话错误。
$response = $this->json('POST',
'/route_in_question',
['first_name' => 'S']
);
$response->assertSessionHasErrors(['first_name');
回答by Yevgeniy Afanasyev
Friends, please, make the unit-test properly, after all, it is not only rules
you are testing here, the validationData
and withValidator
functions may be there too.
朋友们,请好好做单元测试,毕竟rules
这里不只是你在测试,函数validationData
和withValidator
函数也可能在那里。
This is how it should be done:
应该这样做:
<?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));
}
}