Symfony2单元测试表单提交

时间:2014-05-10 11:14:44

标签: php forms unit-testing symfony

我有一个看起来像这样的表格,当它被渲染时:

<form name="service_user_registration" method="post" action="" novalidate="novalidate">

        <div>
             <label for="service_user_registration_user_email" class="required">E-mail</label>
             <input type="email" id="service_user_registration_user_email" name="service_user_registration[user][email]" required="required" size="30" class="sample_class" title="Sample title" placeholder="Your e-mail..." />
        </div>

        <div>
             <label for="service_user_registration_account_name" class="required">Company name</label>
             <input type="text" id="service_user_registration_account_name" name="service_user_registration[account][name]" required="required" placeholder="Your company name..." />
        </div>

        <button type="submit" id="service_user_registration_register" name="service_user_registration[register]" class="btn btn-primary">Register</button>

    <input type="hidden" id="service_user_registration__token" name="service_user_registration[_token]" value="VzkWJQw-2p-1lfBJoT5xwNB4dR2reT47i0ZTZES9LqY" />
</form>

如果我输入的数据写在底层对象(即Registration对象)中,我想对表单提交进行单元测试。我是这样做的,但我不知道如何正确设置$ data数组,因为字段的name属性看起来像一个数组。

class RegistrationTypeTest extends TypeTestCase
{
    public function testSubmit()
    {
        $user = new User();
        $account = new Account();
        $registration = new Registration($user,$account);

        $form = $this->factory->create(new RegistrationType(), $registration);

        $data = array(
            'service_user_registration[user][email]' => 'testing@test.com',
            'service_user_registration[account][name]' => 'New company'
        );

        $form->submit($data);

        $this->assertTrue($form->isSynchronized());

        $formData = $form->getData();

        $this->assertInstanceOf('Service\Bundle\UserBundle\Entity\Registration', $formData);

        $this->assertEquals($data['service_user_registration[user][email]'],   $formData->getUser()->getEmail());
        $this->assertEquals($data['service_user_registration[account][name]'], $formData->getAccount()->getName());
    }
}

最后两个断言失败,因为Registration对象中的$ formData使所有内容都为null,这在提交的字段都为空时应该是这种情况。我也像数组数组一样写了$ data,但没有改变任何东西。

编辑(添加表单类型):

class RegistrationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('user', new RegistrationUserType())
                ->add('account', new RegistrationAccountType())
                ->add('register', 'submit');
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        # Using cascade validation because Valid constraint can not have validation groups

        $resolver->setDefaults([
            'cascade_validation' => true,
            'intention' => $this->getName()
        ]);
    }

    public function getName()
    {
        return 'service_user_registration';
    }
}

class RegistrationUserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('email', 'email');
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'validation_groups' => array('registration'),
            'data_class' => 'Service\Bundle\UserBundle\Entity\User',
            'intention' => $this->getName()
        ));
    }

    public function getName()
    {
        return 'service_user_user_registration';
    }
}

class RegistrationAccountType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name', 'text');
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'validation_groups' => array('registration'),
            'data_class' => 'Service\Bundle\UserBundle\Entity\Account',
            'intention' => $this->getName()
        ));
    }

    public function getName()
    {
        return 'service_user_account_registration';
    }
}

1 个答案:

答案 0 :(得分:4)

然后人们继续抱怨TDD是愚蠢的,它很难,很糟糕,最后,it's dead ......

帮自己一个忙,不要试图单独测试你不应该首先进行单元测试的东西。写一些更高级别的测试。你至少有两个选择。

首先,您可以编写特定于该表单的集成测试,以在更广泛的上下文中测试其行为。例如,您可以创建表单的实例,将数据传递给它,然后测试从表单中获取的模型是否包含您传递的数据。

其次,您可以编写涉及此表单的端到端测试。如果表单不正常,测试将失败。

由于端到端测试通常较慢,因此当表单有效且无效时,您实际上可以编写其中一个或两个以测试代码的行为是否正确。例如,当表单有效时,会保留模型并将用户重定向到某个位置。如果不是,则不会保留任何内容,并且会使用先前输入的数据和验证消息再次显示该表单。

然后你可以编写几个特定于表单的集成测试来测试一些其他数据输入组合,以确保它在这些情况下的行为正确。

实际上,如果您正在测试验证,则可以省略表单本身的集成测试,并在模型上编写测试以测试验证规则。但是您仍然需要端到端测试来测试应用程序的整体流程。