簡體   English   中英

如何測試驗證錯誤在 laravel 單元測試中拋出確切的錯誤和消息

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

如何測試在驗證錯誤中拋出的 php 單元中的特定驗證錯誤? 使用下面的代碼我們可以檢查 session 是否有錯誤,但不是確切的錯誤

$this->assertSessionHasErrors();

assertSessionHasErrors可以接收一個數組,如文檔所示

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

得到了答案

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

$errors 是 MessageBag 對象,當使用 $errors->get('name') 拋出驗證錯誤時,它存儲在 Laravel 會話中,您可以將所有驗證錯誤視為數組

您可以使用assertStatusassertJson的組合

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

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

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

required 屬性的一個例子是

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

$response->assertSessionHasErrors('name');

您可以添加一個額外的斷言,以確保沒有條目被添加到數據庫中,在這種情況下“斷言沒有添加課程”

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

我認為還有一種更優雅的方式:

如果您通過類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.')]);
}

模型/再現功能

如果它被激活,我們會拋出一個異常,然后可以由測試函數檢查。

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

實際上,您可以使用dd()session('errors')輕松地從驗證中拋出錯誤

由於錯誤包存儲在會話中,您可以在單元測試中添加dd(session('errors')以查看缺少哪些字段。

最后你可以通過添加$response->assertSessionHasErrors('field_name');來編寫更合適的測試$response->assertSessionHasErrors('field_name');

首先我使用

$this->post() 

代替

$this->jsonPost()

不知道為什么,由於某種原因,會話不會出來。

然后我就用

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

要找出錯誤消息是什么,您必須轉儲它

$response->dumpSession();

Laravel 7 ; 就我而言,我需要確保沒有錯誤。

但是下面確實忽略了表單驗證錯誤(至少是我的)。

$response->assertSessionHasNoErrors();

因此,我在基本測試用例 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;
}

但是,我的assertHasErrorRegExp(...)可用於 OP 的情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM