Thomas
Thomas

Reputation: 545

PHPSpec symfony2 Form types

I want to test Form types from Symfony2. I have a custom form type and my test looks like this:

/**
 * @param  \Acme\UserBundle\Entity\User $user
 */
function let(\Acme\UserBundle\Entity\User $user)
{
    $this->beConstructedWith($user);
}

function it_is_initializable()
{
    $this->shouldHaveType('Acme\UserBundle\Form\Type\RegistrationFormType');
}

/**
 * @param \Symfony\Component\Form\FormBuilderInterface $builder
 */
function it_builds_form(\Symfony\Component\Form\FormBuilderInterface $builder)
{
    $this->buildForm($builder, []);
}

And I get: Fatal error: Call to a member function add() on a non-object In buildForm method I invoke $this->add method from FormBuilderInterface how can I solve this ?

Upvotes: 0

Views: 680

Answers (1)

Damon Jones
Damon Jones

Reputation: 219

You didn't post your form code, but I suspect that the problem is the fluent interface that the builder's add() method uses. If you have multiple calls to add() like this:

$builder
    ->add('username')
    ->add('email')
    ->add(...)
    ->add(...)
    ->add('save', 'submit');

Then the problem will occur after the first add(), because that isn't returning an object (hence the "Call to a member function add() on a non-object" error message).

If you are using the fluent style, you need to "train" the $builder collaborator, so that phpspec/mockery can return the same builder object for successive calls to add():

$builder->add(Argument::any(), Argument::any())->willReturn($builder);
$this->buildForm($builder, []);

I think that Symfony 2 forms are may not be the best candidate for phpspec testing, as you really want to test only the public API for your classes and not to test code that you don't own (i.e. framework/3rd-party libraries).

The form type that you are testing isn't the actual form that is produced, it's more like the "blueprint" used to build the form when it is needed, so I think it's harder to test that a form has certain fields or options, etc. as this isn't called by your code, it happens automatically when the forms framework processes the form type.

The work to create the real form happens inside the builder, which in the context of this form type spec is a collaborator rather than a real builder object (and also is not your code to test).

Upvotes: 4

Related Questions