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

时间:2016-01-13 12:54:39

标签: validation laravel testing phpunit

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

我用来模拟用户输入:

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

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

如何在不依赖于验证错误的文本的情况下进行相同的测试,并且仅根据错误本身进行测试?

控制器:

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

    return Redirect::back():
}

DD(会话::所有()):

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

5 个答案:

答案 0 :(得分:6)

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

    /** @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上进行了测试

答案 1 :(得分:4)

你可以这样做 -

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

或使用 $this->assertSessionHasErrors();

答案 2 :(得分:0)

您的测试没有发布电话。以下是使用Jeffery Way's flash package

的示例

控制器:

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

测试:

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.');
}

答案 3 :(得分:0)

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

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

适用于Laravel 5 +

答案 4 :(得分:0)

尝试将测试分成多个单元,例如是否测试控制器功能

您可能会发现配偶异常,如下所示:

} 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