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

Validation 测试验证错误的更好方法,validation,laravel,testing,phpunit,Validation,Laravel,Testing,Phpunit,我正在测试一个表单,其中用户必须引入一些介于100到500个字符之间的文本 我用于模拟用户输入: $this->actingAs($user) ->visit('myweb/create') ->type($this->faker->text(1000),'description') ->press('Save') ->see('greater than'); 在这里,我要查找的是响应中的大于的文本片段。。。它取决于为该验证错误指定的翻译 如何在不依赖

我正在测试一个表单,其中用户必须引入一些介于100到500个字符之间的文本

我用于模拟用户输入:

$this->actingAs($user)
->visit('myweb/create')
->type($this->faker->text(1000),'description')
->press('Save')
->see('greater than');
在这里,我要查找的是响应中的
大于
的文本片段。。。它取决于为该验证错误指定的翻译

如何在不依赖验证错误文本的情况下执行相同的测试,并且只依赖于错误本身

控制器:

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

    return Redirect::back():
}
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();
}
dd(会话::all()):


你可以这样做-

$this->assertSessionHas('flash_notification.level','danger')如果您正在查找特定错误或成功密钥

或使用
$this->assertSessionHasErrors()

您的测试没有post调用。下面是一个使用

控制器:

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

    return Redirect::back():
}
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();
}
测试:


从会话erros获取MessageBag对象,并使用
$errors->get('name')


这适用于Laravel 5+

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

    /** @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);
前置要求:代码在Laravel Framework 5.5.14上进行了测试


试着把你的测试分成几个单元,比如你测试一个控制器功能

您可能会捕获有效性异常,如下所示:

} catch (ValidationException $ex) {
如果它是手动生成的,应该这样生成:

throw ValidationException::withMessages([
            'abc' => ['my message'],
        ])->status(400);
你可以这样断言

$this->assertSame('my message', $ex->errors()['abc'][0]);
如果您不能抓住它,但更喜欢这样的测试路线:

    $response = $this->json('POST', route('user-post'), [
        'name'        => $faker->name,
        'email'       => $faker->email,            
    ]);
然后使用$response断言验证已经发生,如下所示

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

在我使用的例子中

$faker = \Faker\Factory::create();
ValidationException的用法如下

use Illuminate\Validation\ValidationException;
只需提醒您不必手动生成异常,对于常见情况,请使用
validate
方法:

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

我当前的laravel版本是
5.7

,即使我真的遇到了验证错误,也无法工作。assertSessionHasErrors()验证为false<代码>会话缺少密钥:断言false为true失败的错误可能与laravel 5.1有关,而不是我的控制器,看:@AyoAkinyemi您显示的不是
验证错误测试
,而是
闪存消息测试
按下保存按钮(
->按下('save')
)也会发送post请求。顺便说一句,您尝试了您的断言,但现在由于以下标记而失败:
testing.ERROR:exception'illumb\Session\tokenmischexception'位于/var/www/html/anuncios.com/vendor/laravel/framework/src/illumb/Foundation/Http/Middleware/VerifyCsrfToken.php:53
添加这些特征。。。数据库事务,没有测试类的中间件。好的,(我也可以
do$this->be($some_user);
)。尽管如此,断言还是失败了,没有抛出flash消息,发布后我用会话的var_转储更新了问题。可能是因为错误是由FormRequest传递的,而不是专门调用FlashFacade`嗯……有趣。。。有什么方法可以聊天吗?如果我们一直评论聊天可能会自动打开,idk任何其他方法您是如何使
request()
函数在unittest中工作的?@YevGeniyafanasev您在调用测试中的
$this->post()
$this->get()
等后调用
request()
。您将调用刚刚发出的请求。>我正在使用phpunit 7.5和Lumen 5.8-当对
请求
或规则使用单元测试时,您可以执行
$this->expectException$this->expectException('light\Validation\ValidationException')
$this->expectExceptionMessage=“名称字段是必需的”-另请注意,异常不包含验证消息(我只得到<代码>给定数据无效<代码>)异常不包含验证消息-由于单个异常可能包含多个验证失败的信息,因此异常包含一组消息<代码>$ex->errors()
$request->validate(['name' => [
            'required',
        ],
    ]);