简体   繁体   English

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

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

How to test specific validation errors in php unit thrown in validation error?如何测试在验证错误中抛出的 php 单元中的特定验证错误? with below code we could check session has errors, but not the exact error使用下面的代码我们可以检查 session 是否有错误,但不是确切的错误

$this->assertSessionHasErrors();

assertSessionHasErrors can receive an array, as documented : assertSessionHasErrors可以接收一个数组,如文档所示

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

Got the answer得到了答案

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

$errors is MessageBag object which stored in laravel session when validation error thrown using $errors->get('name') you could see all the validation errors as an array $errors 是 MessageBag 对象,当使用 $errors->get('name') 抛出验证错误时,它存储在 Laravel 会话中,您可以将所有验证错误视为数组

You may use the combination of assertStatus and assertJson您可以使用assertStatusassertJson的组合

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

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

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

an example for required attribute will be required 属性的一个例子是

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

$response->assertSessionHasErrors('name');

You can add an extra assertion, to make sure that no entry was added to the database, in this case "assert no course was added"您可以添加一个额外的断言,以确保没有条目被添加到数据库中,在这种情况下“断言没有添加课程”

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

For multiple required attributes you may use a loop something like the following:对于多个必需的属性,您可以使用如下所示的循环:

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

There is also a more elegant way in my opinion:我认为还有一种更优雅的方式:

If you throw an exception via the class GeneralException you can check in a unit test if the session has a flash_danger from throwing a exception.如果您通过类GeneralException抛出异常,您可以在单元测试中检查会话是否因抛出异常而产生flash_danger

Lets do a practical example: We want to test that the admin cannot activate an already activated catalogue item.让我们做一个实际的例子:我们想测试管理员不能激活一个已经激活的目录项。

Test function测试功能

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 function模型/再现功能

If it is activated we throw an Exception which then can be checked by the test function.如果它被激活,我们会抛出一个异常,然后可以由测试函数检查。

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

actually you can easily throw errors from validation using dd() and session('errors')实际上,您可以使用dd()session('errors')轻松地从验证中抛出错误

since errors bag is stored in session you could add dd(session('errors') in your unit tests to see which fields you are missing.由于错误包存储在会话中,您可以在单元测试中添加dd(session('errors')以查看缺少哪些字段。

and finally you can write more proper test by adding $response->assertSessionHasErrors('field_name');最后你可以通过添加$response->assertSessionHasErrors('field_name');来编写更合适的测试$response->assertSessionHasErrors('field_name');

First I use首先我使用

$this->post() 

instead of代替

$this->jsonPost()

Dont know why, for certain reason, the session would not come out.不知道为什么,由于某种原因,会话不会出来。

Then I just use然后我就用

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

To find out what are the error message, you must dump it要找出错误消息是什么,您必须转储它

$response->dumpSession();

Laravel 7 ; Laravel 7 ; In my case, I needed to ensure there was no error.就我而言,我需要确保没有错误。

But below did ignore form-validation errors (at least mine).但是下面确实忽略了表单验证错误(至少是我的)。

$response->assertSessionHasNoErrors();

Hence I created a custom assert function in base TestCase class, like:因此,我在基本测试用例 class 中创建了一个自定义断言TestCase ,例如:

use PHPUnit\Framework\Constraint\RegularExpression;

// ...

public static function assertNoErrorReport(TestResponse $response)
{
    $error = static::getViewError($response);
    if ( ! empty($error)) {
        $this->fail('View contains error:' . PHP_EOL . $error);
    }
    $response->assertSessionHasNoErrors();
}

public function assertHasErrorRegExp(string $pattern, TestResponse $response, string $message = '')
{
    $error = static::getViewError($response);
    static::assertThat($error, new RegularExpression($pattern),
        empty($message) ? $error : $message);
}

public static function getViewError(TestResponse $response)
{
    $content = $response->getOriginalContent();
    if ( ! $content) {
        static::fail('View content missing.');
    }
    if ($content instanceof View) {
        $data = $content->gatherData();
        $error = $data['error'] ?? $data['errors'] ?? null;

        // Casts array to string.
        if (is_array($error)) {
            $error = '[' . join(', ', $error) . ']';
        }
        // Casts Error-bag to string.
        $error = '' . $error;
        if ($error === '[]') {
            return null;
        }
    } else {
        static::fail('Response is not a View.');
    }

    return $data;
}

However, my assertHasErrorRegExp(...) could be used for OP's case.但是,我的assertHasErrorRegExp(...)可用于 OP 的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM