【问题标题】:Symfony3 unit testing forms always valid when invalid dataSymfony3 单元测试表单在无效数据时始终有效
【发布时间】:2017-09-30 12:20:05
【问题描述】:

我使用 Symfony3 和表单。我有一个 formType,我想测试它。 我关注这篇文章: http://symfony.com/doc/current/form/unit_testing.html

我的表单类型如下:

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Required;

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $aOption)
    {

        $builder->add('name', TextType::class, array(
            'constraints' => array(
                new NotBlank(),
                new Length(array('min' => 3)),
            ),
        ))
            ->add('age', IntegerType::class, array(
                'constraints' => array(
                    new GreaterThanOrEqual(array('value' => 18)),
                    new Required()),

            ));
    }
}

姓名必须超过 3 个字符,年龄必须超过 18 岁。 我想用 phpunit 进行测试,提交无效数据。我 submut 的年龄无效,因为它小于 18,名称无效,因为它包含 1 个字符。我的测试类如下:

namespace Tests\AppBundle\Controller;

use AppBundle\Form\UserType;
use Symfony\Component\Form\Test\TypeTestCase;
use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
use Symfony\Component\Form\Form;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Validator\ValidatorInterface;

class UserTypeTest extends TypeTestCase
{
    private $validator;
    protected function getExtensions()
    {
        $this->validator = $this->createMock(ValidatorInterface::class);
        // use getMock() on PHPUnit 5.3 or below
        // $this->validator = $this->getMock(ValidatorInterface::class);
        $this->validator
            ->method('validate')
            ->will($this->returnValue(new ConstraintViolationList()));
        $this->validator
            ->method('getMetadataFor')
            ->will($this->returnValue(new ClassMetadata(Form::class)));
        return array(
            new ValidatorExtension($this->validator),
        );
    }
    public function testIndex()
    {
        $formData = array(
            'name' => 'a',
            'age'  => '4'
        );
        $formBuilder = $this->factory->createBuilder(UserType::class);
        $form = $formBuilder->getForm();
        $form->submit($formData);
        $this->assertTrue($form->isSynchronized());
        $this->assertFalse($form->isValid());

    }
}

当我想使用无效数据运行测试以提交时,我失败了:

./vendor/bin/phpunit tests/AppBundle/Controller/UserTypeTest.php  
Failed asserting that true is false.

为什么表单总是有效的?

【问题讨论】:

    标签: php forms symfony unit-testing


    【解决方案1】:

    您的表单始终有效,因为您的 new ConstraintViolationList() 为空。

    我可以建议您将 UserTypeTest::getExtensions() 方法替换为以下内容:

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

    有了这个 ValidatorExtension,你不应该为空 ConstraintViolationList

    【讨论】:

    • 谢谢。我有一个错误:TypeError: Argument 1 passed to Tests\AppBundle\Controller\UserTypeTest::createValidator() must be an instance of Tests\AppBundle\Controller\MetadataFactoryInterface, instance of Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory given
    • 提供的解决方案不起作用,没有这样的课程FakeMetadataFactory
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-27
    • 2010-09-19
    • 2017-06-12
    • 2019-09-27
    • 2015-09-02
    相关资源
    最近更新 更多