如何使用 Symfony 爬虫组件和 PHPUnit 测试提交错误值的表单?
How to test form submission with wrong values using Symfony crawler component and PHPUnit?
当您通过浏览器使用该应用程序时,您发送了错误的值,系统会检查表单中的错误,如果出现问题(在本例中确实如此),它会重定向并显示默认错误信息写在有罪的字段下方。
这是我试图用我的测试用例断言的行为,但我遇到了一个我没有预料到的 \InvalidArgumentException。
我将 symfony/phpunit-bridge 与 phpunit/phpunit v8.5.23 和 symfony/dom-crawler v5.3.7 一起使用。
这是它的外观示例:
public function testPayloadNotRespectingFieldLimits(): void
{
$client = static::createClient();
/** @var SomeRepository $repo */
$repo = self::getContainer()->get(SomeRepository::class);
$countEntries = $repo->count([]);
$crawler = $client->request(
'GET',
'/route/to/form/add'
);
$this->assertResponseIsSuccessful(); // Goes ok.
$form = $crawler->filter('[type=submit]')->form(); // It does retrieve my form node.
// This is where it's not working.
$form->setValues([
'some[name]' => 'Someokvalue',
'some[color]' => 'SomeNOTOKValue', // It is a ChoiceType with limited values, where 'SomeNOTOKValue' does not belong. This is the line that throws an \InvalidArgumentException.
)];
// What I'd like to assert after this
$client->submit($form);
$this->assertResponseRedirects();
$this->assertEquals($countEntries, $repo->count([]));
}
这是我收到的异常消息:
InvalidArgumentException: Input "some[color]" cannot take "SomeNOTOKValue" as a value (possible values: "red", "pink", "purple", "white").
vendor/symfony/dom-crawler/Field/ChoiceFormField.php:140
vendor/symfony/dom-crawler/FormFieldRegistry.php:113
vendor/symfony/dom-crawler/Form.php:75
这里测试的 ColorChoiceType 非常标准:
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'choices' => ColorEnumType::getChoices(),
'multiple' => false,
)];
}
我能做的是将一个 try-catch 块包装起来,即设置错误值的行。它确实会提交表单并继续下一个断言。这里的问题是表单被认为 已提交且有效 ,它强制为颜色字段(枚举集的第一个选择)设置适当的值。
这 不是 我在浏览器中尝试此操作时得到的结果(参见简介)。
// ...
/** @var SomeRepository $repo */
$repo = self::getContainer()->get(SomeRepository::class);
$countEntries = $repo->count([]); // Gives 0.
// ...
try {
$form->setValues([
'some[name]' => 'Someokvalue',
'some[color]' => 'SomeNOTOKValue',
]);
} catch (\InvalidArgumentException $e) {}
$client->submit($form); // Now it submits the form.
$this->assertResponseRedirects(); // Ok.
$this->assertEquals($countEntries, $repo->count([])); // Failed asserting that 1 matches expected 0. !!
如何在我的测试用例中模仿浏览器行为并对其进行断言?
您似乎可以在 DomCrawler\Form 组件上禁用验证。基于官方文档 here.
这样做,现在可以正常工作了:
$form = $crawler->filter('[type=submit]')->form()->disableValidation();
$form->setValues([
'some[name]' => 'Someokvalue',
'some[color]' => 'SomeNOTOKValue',
];
$client->submit($form);
$this->assertEquals($entriesBefore, $repo->count([]); // Now passes.
当您通过浏览器使用该应用程序时,您发送了错误的值,系统会检查表单中的错误,如果出现问题(在本例中确实如此),它会重定向并显示默认错误信息写在有罪的字段下方。
这是我试图用我的测试用例断言的行为,但我遇到了一个我没有预料到的 \InvalidArgumentException。
我将 symfony/phpunit-bridge 与 phpunit/phpunit v8.5.23 和 symfony/dom-crawler v5.3.7 一起使用。 这是它的外观示例:
public function testPayloadNotRespectingFieldLimits(): void
{
$client = static::createClient();
/** @var SomeRepository $repo */
$repo = self::getContainer()->get(SomeRepository::class);
$countEntries = $repo->count([]);
$crawler = $client->request(
'GET',
'/route/to/form/add'
);
$this->assertResponseIsSuccessful(); // Goes ok.
$form = $crawler->filter('[type=submit]')->form(); // It does retrieve my form node.
// This is where it's not working.
$form->setValues([
'some[name]' => 'Someokvalue',
'some[color]' => 'SomeNOTOKValue', // It is a ChoiceType with limited values, where 'SomeNOTOKValue' does not belong. This is the line that throws an \InvalidArgumentException.
)];
// What I'd like to assert after this
$client->submit($form);
$this->assertResponseRedirects();
$this->assertEquals($countEntries, $repo->count([]));
}
这是我收到的异常消息:
InvalidArgumentException: Input "some[color]" cannot take "SomeNOTOKValue" as a value (possible values: "red", "pink", "purple", "white").
vendor/symfony/dom-crawler/Field/ChoiceFormField.php:140
vendor/symfony/dom-crawler/FormFieldRegistry.php:113
vendor/symfony/dom-crawler/Form.php:75
这里测试的 ColorChoiceType 非常标准:
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'choices' => ColorEnumType::getChoices(),
'multiple' => false,
)];
}
我能做的是将一个 try-catch 块包装起来,即设置错误值的行。它确实会提交表单并继续下一个断言。这里的问题是表单被认为 已提交且有效 ,它强制为颜色字段(枚举集的第一个选择)设置适当的值。 这 不是 我在浏览器中尝试此操作时得到的结果(参见简介)。
// ...
/** @var SomeRepository $repo */
$repo = self::getContainer()->get(SomeRepository::class);
$countEntries = $repo->count([]); // Gives 0.
// ...
try {
$form->setValues([
'some[name]' => 'Someokvalue',
'some[color]' => 'SomeNOTOKValue',
]);
} catch (\InvalidArgumentException $e) {}
$client->submit($form); // Now it submits the form.
$this->assertResponseRedirects(); // Ok.
$this->assertEquals($countEntries, $repo->count([])); // Failed asserting that 1 matches expected 0. !!
如何在我的测试用例中模仿浏览器行为并对其进行断言?
您似乎可以在 DomCrawler\Form 组件上禁用验证。基于官方文档 here.
这样做,现在可以正常工作了:
$form = $crawler->filter('[type=submit]')->form()->disableValidation();
$form->setValues([
'some[name]' => 'Someokvalue',
'some[color]' => 'SomeNOTOKValue',
];
$client->submit($form);
$this->assertEquals($entriesBefore, $repo->count([]); // Now passes.