Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Form] Updated unit testing article #13552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 18, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 57 additions & 30 deletions form/unit_testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ factory but it would be complex. It is better to pass it to FormFactory like it
is done in a real application. It is simple to bootstrap and you can trust
the Symfony components enough to use them as a testing base.

There is already a class that you can benefit from for simple FormTypes
testing: :class:`Symfony\\Component\\Form\\Test\\TypeTestCase`. It is used to
test the core types and you can use it to test your types too.
There is already a class that you can benefit from for testing:
:class:`Symfony\\Component\\Form\\Test\\TypeTestCase`. It is used to test the
core types and you can use it to test your types too.

.. note::

Expand Down Expand Up @@ -54,27 +54,35 @@ The simplest ``TypeTestCase`` implementation looks like the following::
'test2' => 'test2',
];

$objectToCompare = new TestObject();
// $objectToCompare will retrieve data from the form submission; pass it as the second argument
$form = $this->factory->create(TestedType::class, $objectToCompare);
$formData = new TestObject();
// $formData will retrieve data from the form submission; pass it as the second argument
$form = $this->factory->create(TestedType::class, $formData);

$object = new TestObject();
$expected = new TestObject();
// ...populate $object properties with the data stored in $formData

// submit the data to the form directly
$form->submit($formData);

// This check ensures there are no transformation failures
$this->assertTrue($form->isSynchronized());

// check that $objectToCompare was modified as expected when the form was submitted
$this->assertEquals($object, $objectToCompare);
// check that $formData was modified as expected when the form was submitted
$this->assertEquals($expected, $formData);
}

public function testCustomFormView()
{
$formData = new TestObject();
// ... prepare the data as you need

$view = $form->createView();
$children = $view->children;
// The initial data may be used to compute custom view variables
$view = $this->factory->create(TestedType::class, $formData)
->createView()
;

foreach (array_keys($formData) as $key) {
$this->assertArrayHasKey($key, $children);
}
$this->assertArrayHasKey('custom_var', $view->vars);
$this->assertSame('expected value', $view->vars['custom_var']);
}
}

Expand All @@ -84,7 +92,7 @@ First you verify if the ``FormType`` compiles. This includes basic class
inheritance, the ``buildForm()`` function and options resolution. This should
be the first test you write::

$form = $this->factory->create(TestedType::class, $objectToCompare);
$form = $this->factory->create(TestedType::class, $formData);

This test checks that none of your data transformers used by the form
failed. The :method:`Symfony\\Component\\Form\\FormInterface::isSynchronized`
Expand All @@ -97,30 +105,38 @@ method is only set to ``false`` if a data transformer throws an exception::

Don't test the validation: it is applied by a listener that is not
active in the test case and it relies on validation configuration.
Instead, unit test your custom constraints directly.
Instead, unit test your custom constraints directly or read how
to :ref:`add custom extensions <form_unit_testing-adding_custom_extensions>`
in the last section of this page.

Next, verify the submission and mapping of the form. The test below
checks if all the fields are correctly specified::
Next, verify the submission and mapping of the form. The test below checks if
all the fields are correctly specified::

$this->assertEquals($object, $objectToCompare);
$this->assertEquals($expected, $formData);

Finally, check the creation of the ``FormView``. You should check if all
widgets you want to display are available in the children property::
Finally, check the creation of the ``FormView``. You can check that a custom
variable exists and will be available in your form themes::

$view = $form->createView();
$children = $view->children;

foreach (array_keys($formData) as $key) {
$this->assertArrayHasKey($key, $children);
}
$this->assertArrayHasKey('custom_var', $view->vars);
$this->assertSame('expected value', $view->vars['custom_var']);

.. tip::

Use :ref:`PHPUnit data providers <testing-data-providers>` to test multiple
form conditions using the same test code.

Testings Types from the Service Container
-----------------------------------------
.. caution::

When your type relies on the ``EntityType``, you should register the
:class:`Symfony\\Bridge\\Doctrine\\Form\\DoctrineOrmExtension`, which will
need to mock the ``ManagerRegistry``.

However, If you cannot use a mock to write your test, you should extend
the ``KernelTestCase`` instead and use the ``form.factory`` service to
create the form.

Testings Types Registered as Services
-------------------------------------

Your form may be used as a service, as it depends on other services (e.g. the
Doctrine entity manager). In these cases, using the above code won't work, as
Expand Down Expand Up @@ -165,14 +181,18 @@ make sure the ``FormRegistry`` uses the created instance::

public function testSubmitValidData()
{
// ...

// Instead of creating a new instance, the one created in
// getExtensions() will be used.
$form = $this->factory->create(TestedType::class);
$form = $this->factory->create(TestedType::class, $formData);

// ... your test
}
}

.. _form_unit_testing-adding_custom_extensions:

Adding Custom Extensions
------------------------

Expand Down Expand Up @@ -211,6 +231,13 @@ allows you to return a list of extensions to register::
// ... your tests
}

.. note::

By Default only the
:class:`Symfony\\Component\\Form\\Extension\\Core\\CoreExtension` is
registered in tests. You can find other extensions from the Form component
in the ``Symfony\Component\Form\Extension`` namespace.

It is also possible to load custom form types, form type extensions or type
guessers using the :method:`Symfony\\Component\\Form\\Test\\FormIntegrationTestCase::getTypes`,
:method:`Symfony\\Component\\Form\\Test\\FormIntegrationTestCase::getTypeExtensions`
Expand Down