簡體   English   中英

帶約束的 Symfony2 單元測試表單

[英]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 方法。

\n

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM