如何使用Symfony爬网程序组件和PHPUnit测试具有错误值的表单提交



当你通过浏览器使用应用程序时,你发送了一个错误的值,系统会检查表单中的错误,如果出现问题(在这种情况下确实如此(,它会重定向,并在incriminated字段下面写一条默认的错误消息。

这是我试图在测试用例中断言的行为,但我遇到了一个我没有预料到的\InvalidArgumentException。

我将symfony/phpunit桥接与phpunit/phpunit v8.5.23和symfony/dom爬网程序v.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组件的验证。基于此处的官方文件。

因此,这样做,现在如预期的那样工作:

$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.

最新更新