<?php
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Test\TypeTestCase;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\PreloadedExtension;
use Doctrine\Persistence\ManagerRegistry;
use PHPSnippets\Db\Entity\Library;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\Mapping\ClassMetadata;
/**
* How more complex Symfony form tests shouldn't be done
* when other form types or dependencies are involved.
*
* More about Symfony form tests can be read here: https://symfony.com/doc/current/form/unit_testing.html
*/
class FormTest extends TypeTestCase
{
private $library;
protected function setUp() : void
{
/*
* Create one entity for the EntityType list.
*
* You usually don't mock or stub VOs or DTOs
*/
$this->library = $this->createMock(Library::class);
$this->library->method('getId')
->willReturn('bar');
$this->library->method('getName')
->willReturn('bar');
parent::setUp();
}
/**
* Testing the FooType form type
*/
public function testFormType() : void
{
$formData = [
'foo' => 'foo',
'library' => 'bar',
];
$objectToCompare = new Foo();
$form = $this->factory->create(FooType::class, $objectToCompare);
$object = new Foo();
$object->foo = 'foo';
$object->library = $this->library;
$form->submit($formData);
$this->assertTrue($form->isSynchronized());
$this->assertEquals($object, $objectToCompare);
$view = $form->createView();
$children = $view->children;
foreach (array_keys($formData) as $key) {
$this->assertArrayHasKey($key, $children);
}
}
protected function getExtensions()
{
/*
* Creating mocks/stubs for the EntityType.
*
* These mocks/stubs for the EntityType are a huge
* effort and overhead, that makes a unit test for
* form types more complicated. Symfony form tests
* should usually be more of an integration/functional
* test type.
*/
$query = $this->createMock(AbstractQuery::class);
$query->method('execute')
->willReturn([$this->library]);
$queryBuilder = $this->createMock(QueryBuilder::class);
$queryBuilder->expects(self::once())
->method('getQuery')
->willReturn($query);
$repository = $this->createMock(EntityRepository::class);
$repository->method('createQueryBuilder')
->with('e', null)
->willReturn($queryBuilder);
$metaData = $this->createMock(ClassMetadata::class);
$metaData = new ClassMetadata(Library::class);
$entityManager = $this->createMock(EntityManagerInterface::class);
$entityManager->method('getRepository')
->with(Library::class)
->willReturn($repository);
$entityManager->method('getClassMetadata')
->with(Library::class)
->willReturn($metaData);
$registry = $this->createMock(ManagerRegistry::class);
$registry->method('getManagerForClass')
->with(Library::class)
->willReturn($entityManager);
$entityType = new EntityType($registry);
return [
new PreloadedExtension([$entityType], []),
];
}
}
/**
* The custom form type that is tested.
*/
class FooType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('foo', TextType::class, [
'label' => 'Text',
])->add('library', EntityType::class, [
'label' => 'Field',
'class' => Library::class,
'choice_label' => 'name',
'choice_value' => 'id',
]);
}
}
/**
* The DTO for FooType the form type.
*/
class Foo
{
public $foo;
public $library;
}