支持 Laravel.io 的持续发展 →

测试 Laravel 验证响应

2020年6月28日 阅读时间:6分钟

上周,我正在为一个使用requiredIf验证规则的项目工作。无论我写多少次测试,我总是需要参考Laravel测试文档,以确保我使用正确的断言方法和正确传递参数。

场景描述

在这个帖子中,我将使用一个食谱网站的示例,用户可以记录更改请求。用户需要提供哪些信息取决于他们记录的更改请求类型。如果他们想要更改配料,则需要完成配料列表。如果他们想要更改摘要,则用户需要提供新的摘要。

以下是为存储新的更改请求的用户表单中定义的验证规则。

public function rules()
{
	return [
		'recipe_id' => 'required|integer|exists:recipes,id',
		'change_type' => 'required|in:ingredients,summary',
		'ingredients' => 'nullable|requiredIf:change_type,ingredients|array',
		'ingredients.*' => 'required',
		'summary' => 'nullable|requiredIf:change_type,summary'
	]
}

assertSessionHasNoErrors

如果您正在编写功能测试,则可以编写一个测试确保一切正常,并且没有返回验证错误,通过断言会话没有错误来测试响应。

public function test_can_create_ingredients_change_requests()
{
	$response = $this->post(route('change-request.store'), [
		'recipe_id' => 1,
		'change_type' => 'ingredients',
		'ingredients' => [
			'Flour',
			'Eggs',
			'Milk'
		]
	]);
	$response->assertSessionHasNoErrors();
}

这是一个简单的断言,但它证明在尝试创建配料更改类型的请求时没有返回验证错误。为了更全面地测试,您将想要测试它对于摘要类型更改请求是否也按预期工作。

public function test_can_create_summary_change_requests()
{
	$response = $this->post(route('change-request.store'), [
		'recipe_id' => 1,
		'change_type' => 'summary',
		'summary' => 'This recipe uses basic ingredients but packs a fantastic flavour!'
	]);
	$response->assertSessionHasNoErrors();
}

更新验证规则

如果我们通过添加60个字符的最大长度来修改验证规则,则第二个测试现在将失败。以下是我们的更新规则。

'summary' => 'nullable|requiredIf:change_type,summary|max:60'

失败的测试有一个有用的错误信息,告诉我们它失败的具体原因。

Session has unexpected errors: 
[
    "The summary may not be greater than 60 characters."
]
Failed asserting that true is false.

如果我们想测试具体的失败,可以稍微增加一些测试细节。

AssertSessionDoesntHaveErrors

如果你阅读了测试中的assertSessionHasNoErrorsassertSessionDoesntHaveErrors这两个方法,可能会认为它们是可互换的,因为它们听起来非常相似。它们之间的大区别在于,你可以向assertSessionDoesentHaveErrors传递参数以使测试更具体。

Laravel文档为这个断言方法提供了以下指南。

$response->assertSessionDoesntHaveErrors($keys = [], $format = null, $errorBag = 'default');

如果 честно说,我花了一些时间去记住这些参数的含义。如果你创建自定义错误包,可以将$errorBag从默认值更改为自己的错误包,而$keys是一个我们想要测试的字段数组。《code>$format我没有设置为除了默认值null之外的任何值。如果你已经修改了格式,请随时在注释中添加说明你何时这样做。

现在我们可以在测试中传递我们想要确保没有错误的键。如果其中之一有错误,则消息将指出哪些键有错误。

public function test_can_create_summary_change_requests()
{
	$response = $this->post(route('change-request.store'), [
		'recipe_id' => 1,
		'change_type' => 'summary',
		'summary' => 'This recipe uses basic ingredients but packs a fantastic flavour!'
	]);
	$response->assertSessionDoesntHaveErrors([
		'recipe_id',
		'change_type',
		'summary'
	]);
	$response->assertSessionHasNoErrors();
}

assertSessionHasNoErrors仍然可以作为次要的断言,只是为了再次确认没有其他验证错误被返回。

AssertSessionHasErrors

我们还可以测试与上一个测试相反的情况。而不是测试一切是否都正常工作,我们可以测试验证规则在期望返回验证失败时是否确实返回了验证失败。这些作为更细粒度的单元测试比作为功能测试效果更好。

要测试返回了验证错误,我们可以使用assertSessionHasErrors

$response->assertSessionHasErrors(array $keys, $format = null, $errorBag = 'default');

我们可以使用这个方法来确保摘要字段返回验证错误,以证明它是必需的,并且它的长度小于60个字符。

public function test_summary_is_required_when_summary_change_type()
{
	$response = $this->post(route('change-request.store'), [
		'recipe_id' => 1,
		'change_type' => 'summary',
		'summary' => null
	]);
	$response->assertSessionHasErrors(['summary']);
}

public function test_summary_is_shorter_than_60_characters()
{
	$response = $this->post(route('change-request.store'), [
		'recipe_id' => 1,
		'change_type' => 'summary',
		'summary' => 'This recipe uses basic ingredients but packs a fantastic flavour!'
	]);
	$response->assertSessionHasErrors(['summary']);
}

虽然每个测试都会证明每个场景都会出现验证错误,但这实际上并没有测试请求是否确实触发了我们想要测试的验证规则。在某些情况下,它可能会触另一个摘要的验证规则而仍然失败。

为了更具体地测试,我们可以将期望返回的消息添加到$keys数组中。

public function test_summary_is_required_when_summary_change_type()
{
	$response = $this->post(route('change-request.store'), [
		'recipe_id' => 1,
		'change_type' => 'summary',
		'summary' => null
	]);
	$response->assertSessionHasErrors([
		'summary' => 'The summary field is required when change type is summary.'
	]);
}

public function test_summary_is_shorter_than_60_characters()
{
	$response = $this->post(route('change-request.store'), [
		'recipe_id' => 1,
		'change_type' => 'summary',
		'summary' => 'This recipe uses basic ingredients but packs a fantastic flavour!'
	]);
	$response->assertSessionHasErrors([
		'summary' => 'The summary may not be greater than 60 characters.'
	]);
}

默认验证消息的列表在Laravel项目的resources/lang/en/validation.php文件中的语言文件中,也可以在GitHub上的[https://github.com/laravel/laravel/blob/master/resources/lang/en/validation.php](https://github.com/laravel/laravel/blob/master/resources/lang/en/validation.php)上查看,你可以使用这些信息来帮助你编写测试。

总结

希望这能给你提供一个从哪里开始测试验证规则的想法,同时也帮助你从测试中获得更具体的错误消息,这有助于更容易地调试你的代码。

如果你想了解更多关于Laravel测试的信息,请考虑阅读有关使用工厂和工厂状态清理测试的技术的文章。

最后更新1年前。

driesvints, symiel, eshanit, yvan-burrie 喜欢了这篇文章

4
喜欢这篇文章?让作者知道并给他们鼓掌!
chrisrhymes(Chris Rhymes) 专注于Laravel和Vue.js的网页开发者。我还创建了一些Jekyll主题。

你可能还想阅读的其他文章

2024年3月11日

如何利用Larastan将您的Laravel应用从0到9提升

在Laravel应用尚未执行之前就发现其中的错误是可能的,多亏了Larastan,它...

阅读文章
2024年7月19日

不加特质标准化API响应

我发现大多数用于API响应的库都是使用特质实现的,并且...

阅读文章
2024年7月17日

在您的Laravel项目中通过Discord通知收集反馈

如何在Laravel项目中创建一个反馈模块,并在收到消息时收到Discord通知...

阅读文章

我们想感谢这些 极佳的公司 对我们的支持

您的标志在这里?

Laravel.io

Laravel问题解决、知识共享和社区建设的门户。

© 2024 Laravel.io - 版权所有。