如何使用Symfony爬虫组件和PHPUnit测试提交错误值的表单提交?

5
当您通过浏览器使用应用程序时,如果发送了错误的值,则系统会检查表单中是否存在错误。如果出现问题(在这种情况下),它将在被指控的字段下方重定向并显示默认错误消息。
这是我试图在我的测试用例中验证的行为,但我遇到了一个意外的无效参数异常。
我正在使用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. !!

如何在我的测试用例中模拟浏览器行为并对其进行断言?

1个回答

4

看起来你可以在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.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接