[英]Symfony2 Unit Testing Forms with constraints
我有一个未连接到实体但确实具有此处提到的约束的表单: http : //symfony.com/doc/current/book/forms.html#adding-validation
ContactBundle\\Tests\\Form\\Type\\TestedTypeTest::testSubmitValidData Symfony\\Component\\OptionsResolver\\Exception\\InvalidOptionsException:选项“约束”不存在。 已知选项有:“action”、“attr”、“auto_initialize”、“block_name”、“by_reference”、“compound”、“data”、“data_class”、“disabled”、“empty_data”、“error_bubbling”、“inherit_data” ", "label", "label_attr", "mapped", "max_length", "method", "pattern", "post_max_size_message", "property_path", "read_only", "required", "translation_domain", "trim", “虚拟的”
这是表格的一部分:
class ContactType extends AbstractType
{
/**
* Build the form
* @param \Symfony\Component\Form\FormBuilderInterface $builder BuilderInterface
* @param array $aOption Array of options
*/
public function buildForm(FormBuilderInterface $builder, array $aOption)
{
///..
$builder->add('name', 'text', array(
'constraints' => array(
new NotBlank(),
new Length(array('min' => 3)),
),
))
->add('address', 'textarea', array(
'required' => false
))
//..
;
//..
这是单元测试
class TestedTypeTest extends TypeTestCase
{
public function testSubmitValidData()
{
$formData = array(
'name' => 'Test Name',
'address' => '',
);
$type = new ContactType();
$form = $this->factory->create($type, $formData);
$form->submit($formData);
$this->assertTrue($form->isSynchronized());
$view = $form->createView();
$children = $view->children;
foreach (array_keys($formData) as $key) {
$this->assertArrayHasKey($key, $children);
}
}
}
我猜这是测试而不是表单的问题,因为表单按预期工作。 我不确定我应该改变什么。 任何帮助或建议都会很方便
谢谢
我认为问题在于您还将 formData 传递给工厂的 create 方法。
通过
$form->submit($formData)
传递表单数据应该
$form->submit($formData)
就像你已经在你的代码中一样
更多文档: http : //symfony.com/doc/current/cookbook/form/unit_testing.html
编辑:
好吧,似乎您必须在测试设置中将验证器/containt 扩展添加到工厂对象,如此处所述http://symfony.com/doc/current/cookbook/form/unit_testing.html#adding-custom-extensions
是的,Rob 是对的,我需要添加验证器/约束扩展。 像这样:
class TestedTypeTest extends TypeTestCase
{
protected function setUp()
{
parent::setUp();
$validator = $this->getMock('\Symfony\Component\Validator\Validator\ValidatorInterface');
$validator->method('validate')->will($this->returnValue(new ConstraintViolationList()));
$formTypeExtension = new FormTypeValidatorExtension($validator);
$coreExtension = new CoreExtension();
$this->factory = Forms::createFormFactoryBuilder()
->addExtensions($this->getExtensions())
->addExtension($coreExtension)
->addTypeExtension($formTypeExtension)
->getFormFactory();
}
//..
我建议你覆盖 TypeTestCase::getExtensions() 方法
use Symfony\Component\Form\Extension\Core\CoreExtension;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
use Symfony\Component\Form\Form;
use Symfony\Component\Translation\IdentityTranslator;
use Symfony\Component\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\Context\ExecutionContextFactory;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
use Symfony\Component\Validator\Validator\RecursiveValidator;
....
public function getExtensions()
{
$extensions = parent::getExtensions();
$metadataFactory = new FakeMetadataFactory();
$metadataFactory->addMetadata(new ClassMetadata( Form::class));
$validator = $this->createValidator($metadataFactory);
$extensions[] = new CoreExtension();
$extensions[] = new ValidatorExtension($validator);
return $extensions;
}
在您的测试类中添加方法 createValidator() :
protected function createValidator(MetadataFactoryInterface $metadataFactory, array $objectInitializers = array())
{
$translator = new IdentityTranslator();
$translator->setLocale('en');
$contextFactory = new ExecutionContextFactory($translator);
$validatorFactory = new ConstraintValidatorFactory();
return new RecursiveValidator($contextFactory, $metadataFactory, $validatorFactory, $objectInitializers);
}
不需要覆盖 TypeTestCase::getTypeExtensions() 因为 ValidatorExtension 类已经有一个 loadTypeExtensions() 方法。
然后,您的测试方法可以是这样的:
public function testSubmitValidData()
{
$formData = array(
'name' => 'Test Name',
'address' => '',
);
$form = $this->factory->create(ContactType::class);
$form->submit($formData);
$this->assertTrue($form->isValid());
$this->assertTrue($form->isSynchronized());
$view = $form->createView();
$children = $view->children;
foreach (array_keys($formData) as $key) {
$this->assertArrayHasKey($key, $children);
}
}
您可以测试无效数据:
public function testSubmitInvalidValidData()
{
$formData = array(
'name' => 'T',
);
$form = $this->factory->create(ContactType::class);
$form->submit($formData);
$this->assertFalse($form->isValid());
$this->assertFalse($view->children['name']->vars['valid']);
}
来源:
这个问题在 Symfony 4.4 中仍然会出现,但很容易解决。
ValidatorExtensionTrait
必须添加到运行测试的类中。
use Symfony\Component\Form\Test\TypeTestCase;
class TestedTypeTest extends TypeTestCase
{
use \Symfony\Component\Form\Test\Traits\ValidatorExtensionTrait;
public function testSubmitValidData()
{
$formData = [...];
$type = new ContactType();
$form = $this->factory->create($type, $formData);
}
}
该特征负责添加使“约束”选项可用所需的扩展。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.