[英]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 會話中,您可以將所有驗證錯誤視為數組
您可以使用assertStatus
和assertJson
的組合
...
->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.