具有约束的Symfony2单元测试表单

时间:2014-11-19 16:05:33

标签: php forms unit-testing symfony

我有一个表格没有连接到某个实体,但确实有如下所述的约束:http://symfony.com/doc/current/book/forms.html#adding-validation

  

ContactBundle \测试\表格\型号\ TestedTypeTest :: testSubmitValidData   Symfony \ Component \ OptionsResolver \ Exception \ InvalidOptionsException:选项"约束"不存在。已知选项包括:"操作"," attr"," auto_initialize"," block_name"," by_reference",& #34;复合","数据"," data_class","禁用"," empty_data"," error_bubbling&# 34;," inherit_data","标签"," label_attr","映射"," max_length",&# 34;方法","模式"," post_max_size_message"," property_path"," read_only"," required&#34 ;," translation_domain"," trim"," virtual"

以下是表格的一部分:

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);
    }
}
}

我猜测这是测试而不是表单的问题,因为表单按预期工作。我不确定应该改变什么。 任何帮助或建议都会很方便

由于

4 个答案:

答案 0 :(得分:5)

是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();
}
//..

答案 1 :(得分:3)

我认为问题是你也将formData传递给工厂的create方法。

<击>

只需通过代码中已有的$form->submit($formData)传递表单数据

更多文档:http://symfony.com/doc/current/cookbook/form/unit_testing.html

修改

好吧,您似乎必须在测试设置中将validator / constaint扩展添加到工厂对象,如此处所述http://symfony.com/doc/current/cookbook/form/unit_testing.html#adding-custom-extensions

答案 2 :(得分:1)

我建议你覆盖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']);

}
来源:

答案 3 :(得分:1)

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);
    }
}

特质负责添加使“约束”选项可用所需的扩展名。