laravel 测试验证错误的更好方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34767309/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 13:02:25  来源:igfitidea点击:

Better way for testing validation errors

validationlaraveltestingphpunit

提问by vivoconunxino

I'm testing a form where user must introduce some text between let's say 100 and 500 characters.

我正在测试一个表单,用户必须在其中引入一些文本,比如 100 到 500 个字符。

I use to emulate the user input:

我用来模拟用户输入:

$this->actingAs($user)
->visit('myweb/create')
->type($this->faker->text(1000),'description')
->press('Save')
->see('greater than');

Here I'm looking for the greater thanpiece of text in the response... It depends on the translation specified for that validation error.

在这里,我正在寻找greater than响应中的一段文本......这取决于为该验证错误指定的翻译。

How could do the same test without having to depend on the text of the validation error and do it depending only on the error itself?

如何在不依赖验证错误的文本的情况下进行相同的测试,而只依赖于错误本身呢?

Controller:

控制器:

public function store(Request $request)
{
    $success = doStuff($request);
    if ($success){
        Flash::success('Created');
    } else {
        Flash::error('Fail');
    }

    return Redirect::back():
}

dd(Session::all()):

dd(会话::全部()):

 `array:3 [
  "_token" => "ONoTlU2w7Ii2Npbr27dH5WSXolw6qpQncavQn72e"
  "_sf2_meta" => array:3 [
    "u" => 1453141086
    "c" => 1453141086
    "l" => "0"
  ]
  "flash" => array:2 [
    "old" => []
    "new" => []
  ]
]

采纳答案by Ayo Akinyemi

you can do it like so -

你可以这样做 -

$this->assertSessionHas('flash_notification.level', 'danger');if you are looking for a particular error or success key.

$this->assertSessionHas('flash_notification.level', 'danger');如果您正在寻找特定的错误或成功键。

or use $this->assertSessionHasErrors();

或使用 $this->assertSessionHasErrors();

回答by yuklia

I think there is more clear way to get an exact error message from session.

我认为有更清晰的方法可以从会话中获取确切的错误消息。

    /** @var ViewErrorBag $errors */
    $errors = request()->session()->get('errors');
    /** @var array $messages */
    $messages = $errors->getBag('default')->getMessages();
    $emailErrorMessage = array_shift($messages['email']);

    $this->assertEquals('Already in use', $emailErrorMessage);

Pre-requirements: code was tested on Laravel Framework 5.5.14

前置要求:代码在 Laravel Framework 5.5.14 上测试

回答by Ayo Akinyemi

Your test doesn't have a post call. Here is an example using Jeffery Way's flash package

您的测试没有后期调用。这是使用Jeffery Way 的 flash 包的示例

Controller:

控制器:

public function store(Request $request, Post $post)
{
    $post->fill($request->all());
    $post->user_id = $request->user()->id;

    $created = false;

    try {
        $created = $post->save();
    } catch (ValidationException $e) {
        flash()->error($e->getErrors()->all());
    }

    if ($created) {
        flash()->success('New post has been created.');
    }

    return back();
}

Test:

测试:

public function testStoreSuccess()
{
    $data = [
        'title' => 'A dog is fit',
        'status' => 'active',
        'excerpt' => 'Farm dog',
        'content' => 'blah blah blah',
    ];

    $this->call('POST', 'post', $data);

    $this->assertTrue(Post::where($data)->exists());
    $this->assertResponseStatus(302);
    $this->assertSessionHas('flash_notification.level', 'success');
    $this->assertSessionHas('flash_notification.message', 'New post has been created.');
}

回答by User123456

get the MessageBag object from from session erros and get all the validation error names using $errors->get('name')

从会话错误中获取 MessageBag 对象并使用获取所有验证错误名称 $errors->get('name')

    $errors = session('errors');
    $this->assertSessionHasErrors();
    $this->assertEquals($errors->get('name')[0],"The title field is required.");

This works for Laravel 5 +

这适用于 Laravel 5 +

回答by Yevgeniy Afanasyev

try to split your tests into units, say if you testing a controller function

尝试将您的测试拆分为多个单元,比如您是否在测试控制器功能

you may catch valication exception, like so:

您可能会捕获验证异常,如下所示:

} catch (ValidationException $ex) {

if it was generated manually, this is how it should be generated:

如果它是手动生成的,则应该是这样生成的:

throw ValidationException::withMessages([
            'abc' => ['my message'],
        ])->status(400);

you can assert it liks so

你可以这样断言它

$this->assertSame('my message', $ex->errors()['abc'][0]);

if you cannot catch it, but prefer testing routs like so:

如果你不能抓住它,但更喜欢像这样测试路线:

    $response = $this->json('POST', route('user-post'), [
        'name'        => $faker->name,
        'email'       => $faker->email,            
    ]);

then you use $response to assert that the validation has happened, like so

然后你使用 $response 来断言验证已经发生,就像这样

$this->assertSame($response->errors->{'name'}[0], 'The name field is required.');

PS

聚苯乙烯

in the example I used

在我使用的例子中

$faker = \Faker\Factory::create();

ValidationException is used liks this

ValidationException 像这样使用

use Illuminate\Validation\ValidationException;

just remind you that you don't have to generate exceptions manually, use validatemethod for common cases:

只是提醒您,您不必手动生成异常,validate对于常见情况使用方法:

$request->validate(['name' => [
            'required',
        ],
    ]);

my current laravel version is 5.7

我目前的 Laravel 版本是 5.7