如何测试验证错误在 laravel 单元测试中抛出确切的错误和消息

How to test validation errors throw exact error and message in laravel unit tests

如何测试 php 单元中抛出验证错误的特定验证错误? 使用下面的代码我们可以检查会话是否有错误,但不是确切的错误

$this->assertSessionHasErrors();

得到答案

    $errors = session('errors');
    $this->assertSessionHasErrors();
    $this->assertEquals($errors->get('name')[0],"Your error message for validation");

$errors 是抛出验证错误时存储在 laravel 会话中的 MessageBag 对象 使用 $errors->get('name') 您可以将所有验证错误视为数组

assertSessionHasErrors可以接收一个数组,as documented:

$this->assertSessionHasErrors([
    'field' => 'Field error message.'
]);

还有一种我认为比较优雅的方式:

如果您通过 class GeneralException 抛出异常,您可以检查单元测试是否会话具有 flash_danger 避免抛出异常。

做一个实际的例子:我们想测试管理员不能激活一个已经激活的目录项。

测试函数

public function an_admin_cannot_activate_an_activated_catalogue()
{
    $catalogue = factory(Catalogue::class)->states('active')->create();
    $response = $this->get("/admin/questionnaire/catalogue/{$catalogue->id}/activate");
    $response->assertSessionHas(['flash_danger' => __('The catalogue item is already activated.')]);
}

Model/Repro函数

如果它被激活,我们抛出一个异常,然后可以由测试函数检查。

public function activate(Catalogue $catalogue) : Catalogue
{
    if ($catalogue->is_active) {
        throw new GeneralException(__('The catalogue item is already activated.'));
    }

    $catalogue->is_active = 1;
    $activated = $catalogue->save();

    if($activated) {
        return $catalogue;
    }
}

您可以使用 assertStatusassertJson

的组合
...
->assertStatus(422)
->assertJson([
     'errors' => [
          'field' => [
               'Error message'  
          ]
      ]
]);

您可以使用 $response->assertSessionHasErrors('key')

https://laravel.com/docs/7.x/http-tests#assert-session-has-errors

所需属性的示例为

$response = $this->json('POST', '/api/courses', $this->data([
    'name' => '',
    'api_token' => $this->user->api_token
]));

$response->assertSessionHasErrors('name');

您可以添加一个额外的断言,以确保没有条目被添加到数据库中,在本例中 "assert no course was added"

$this->assertCount(0, Course::all());

对于多个必需的属性,您可以使用如下所示的循环:

collect(['name', 'description', 'amount'])->each(function ($field) {
    $response = $this->json('POST', '/api/courses', $this->data([
        $field => '',
        'api_token' => $this->user->api_token
    ]));

    $response->assertSessionHasErrors($field);
    $this->assertCount(0, Course::all());
});

实际上,您可以使用 dd()session('errors')

轻松抛出验证错误

由于错误包存储在会话中,您可以在单元测试中添加 dd(session('errors')) 以查看缺少哪些字段。

最后你可以通过添加 $response->assertSessionHasErrors('field_name');

来编写更合适的测试

首先我用

$this->post() 

而不是

$this->jsonPost()

不知道为什么,出于某种原因,会话不会出来。

那我就用

$response->assertSessionHasErrors('field_name', 'Error Message!');

要找出错误信息是什么,你必须转储它

$response->dumpSession();