phpsymfonysymfony-3.4

Unable to write a basic TypeTestCase unit test for a Symfony form


I want to test that I convert form data correctly, and so I wrote a unit test based on how the Symfony 3.4 docs instruct me to. It is even marked as the basics, so I did not expect any issues, but I do!

When running the following test I get ArgumentCountError : Too few arguments to function Symfony\Bridge\Doctrine\Form\Type\DoctrineType::__construct(), 0 passed in /Users/.../vendor/symfony/symfony/src/Symfony/Component/Form/FormRegistry.php on line 92 and exactly 1 expected . I see this is more or less what this guy got, but I could not make sense of it.

<?php

namespace Tests\MyProject\BackendBundle;

use MyProject\BackendBundle\Entity\ExerciseInfo;
use MyProject\BackendBundle\Form\ApiExerciseInfoType;
use Symfony\Component\Form\Test\TypeTestCase;

class FormBuilderOfExerciseInfoTest extends TypeTestCase
{

    public function test_something()
    {
        $requestEntry = array(
            'score_cols' =>
                array(
                    0 => 'REPS',
                    1 => 'PAUSE',
                    2 => 'KG_WEIGHTS',
                ),
            'id' => 'C4F1D2A3-762D-4548-B0E3-C0B3912FC02C',
            'score_vals' =>
                array(
                    0 =>
                        array(
                            'type' => 'REPS',
                            'value' =>
                                array(
                                    0 => 12,
                                    1 => 12,
                                    2 => 12,
                                ),
                        ),
                    1 =>
                        array(
                            'type' => 'PAUSE',
                            'value' =>
                                array(
                                    0 => 10,
                                    1 => 10,
                                    2 => 10,
                                ),
                        ),
                    2 =>
                        array(
                            'type' => 'KG_WEIGHTS',
                            'value' =>
                                array(
                                    0 => 0,
                                    1 => 0,
                                    2 => 0,
                                ),
                        ),
                ),
            'score_count' => 3,
            'exercise_id' => 'b9c90921-a594-4c2c-b9df-071357fd5247',
            'notes_sets' =>
                array(
                    0 => '',
                    1 => '',
                    2 => '',
                ),
            'result_vals' =>
                array(),
            'exercise_notes' => '',
            'score_type' => 'REPS',
        );

        $model = new ExerciseInfo();
        $form = $this->factory->create(ApiExerciseInfoType::class, $model);
        $form->submit($requestEntry);

        /**
         * @var $data ExerciseInfo
         */
        $data = $form->getData();
        $exerciseSuperSet = $data->getScoreCols();
        self::assertFalse(empty($exerciseSuperSet));
    }
}

Form type

class ApiExerciseInfoType extends AbstractType
{

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('id', HiddenType::class)
            ->add('exercise_id', EntityType::class, [
                'class' => 'PETE\BackendBundle\Entity\Exercise',
                'property_path' => 'exercise',
            ])
            ->add('notes_sets', null, [])
            ->add('exercise_notes', null, [])
            ->add('score_cols', TextType::class, [
                'property_path' => 'scoreCols'
            ])
            ->add('score_type', TextType::class, [
                'property_path' => 'scoreType'
            ])
            ->add('score_count', null, [
                'property_path' => 'scoreCount',
            ])
            ->add('score_vals', null, [
                'property_path' => 'scoreVals',
            ])
            ->add('result_vals', null, [
                'property_path' => 'resultVals',
            ])
        ;


    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'PETE\BackendBundle\Entity\ExerciseInfo',
            'csrf_protection' => false,
            'allow_extra_fields' => true,
        ));
    }

    public function getBlockPrefix()
    {
        return '';
    }
}

Solution

  • I will list up what I actually did, which is turn this into a kind of integration test, using the container, by extending KernelTestCase instead of TypeTestCase and asking the container for the form factory. Hopefully there is a better way.

    class FormBuilderOfExerciseInfoTest extends KernelTestCase
    {
    
        public function test_something()
        {
            $kernel = self::bootKernel();
    
            /**
             * @var $container ContainerInterface
             */
            $container = $kernel->getContainer();
    
            $requestEntry = array(
                'score_cols' =>
                    array(
                        0 => 'REPS',
                        1 => 'PAUSE',
                        2 => 'KG_WEIGHTS',
                    ),
    ...
    
            $model = new ExerciseInfo();
            $formFactory = $container->get("form.factory");
            $form = $formFactory->create(ApiExerciseInfoType::class, $model);
    ...