如何在测试中加载表单类型


How to load form types in tests

<?php
namespace Tabl'VenueBundle'Tests'Form;
use Symfony'Component'Form'Test'TypeTestCase;
use Tabl'VenueBundle'Entity'Venue;
use Tabl'VenueBundle'Form'VenueType;
class VenueTypeTest extends TypeTestCase
{
    public function testSubmitValidData() {
        $formData = array(
            'title' => 'Hello World',
        );
        $type = new VenueType();
        $form = $this->factory->create($type);
        $object = new Venue();
        $object->setTitle('Hello World');
        // submit the data to the form directly
        $form->submit($formData);
        $this->assertTrue($form->isSynchronized());
        $this->assertEquals($object, $form->getData());
        $view = $form->createView();
        $children = $view->children;
        foreach (array_keys($formData) as $key) {
            $this->assertArrayHasKey($key, $children);
        }
    }
}

我不断收到此错误消息:

Symfony'Component'Form'Exception'InvalidArgumentException: Could not load type "places_autocomplete"

如何解决这个问题?如何加载此类型,以便我可以在窗体上执行功能测试?

places_autocomplete是象牙GMaps捆绑包的一部分。

场地类型.php:

namespace Acme'VenueBundle'Form;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
use Symfony'Bundle'FrameworkBundle'Routing'Router;
use Acme'VenueBundle'Entity'Attribute;
use Acme'VenueBundle'Form'AttributeType;
class VenueType extends AbstractType {
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('address', 'places_autocomplete' , ['attr' => ['placeholder' => 'Start typing for suggestions'], 'label'=>'Location'])
            ->add('attributes', 'entity', array(
                'multiple'      => true,
                'expanded'      => true,
                'property'      => 'icon',
                'class'         => 'AcmeVenueBundle:Attribute',
            ))
            ->add('finish', 'submit');
    }
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Acme'VenueBundle'Entity'Venue'
        ));
    }
    public function getName()
    {
        return 'venue';
    }
}

您必须实现getExtensions方法来构建表单中使用的两种模拟表单类型:PlacesAutocompleteTypeEntityType

此解决方案对我有用:

<?php

namespace Acme'DemoBundle'Tests'Form;

use Doctrine'Common'Collections'ArrayCollection;
use Doctrine'ORM'Mapping'ClassMetadata;
use Ivory'GoogleMapBundle'Form'Type'PlacesAutocompleteType;
use Symfony'Bridge'Doctrine'Form'Type'EntityType;
use Symfony'Component'Form'PreloadedExtension;
use Symfony'Component'Form'Test'TypeTestCase;
use Acme'DemoBundle'Entity'Venue;
use Acme'DemoBundle'Form'VenueType;
class VenueTypeTest extends TypeTestCase
{
public function testSubmitValidData() {
    $formData = array(
        'title' => 'Hello World',
    );
    $type = new VenueType();
    $form = $this->factory->create($type);
    $object = new Venue();
    $object->setTitle('Hello World');
    // submit the data to the form directly
    $form->submit($formData);
    $this->assertTrue($form->isSynchronized());
    $this->assertEquals($object, $form->getData());
    $view = $form->createView();
    $children = $view->children;
    foreach (array_keys($formData) as $key) {
        $this->assertArrayHasKey($key, $children);
    }
}

protected function getExtensions()
{
    // Mock the FormType: places_autocomplete
    // See Ivory'GoogleMapBundle'Tests'Form'Type'PlacesAutocompleteTypeTest
    $placesAutocompleteHelperMock = $this->getMockBuilder('Ivory'GoogleMap'Helper'Places'AutocompleteHelper')
        ->disableOriginalConstructor()
        ->getMock();
    $requestMock = $this->getMock('Symfony'Component'HttpFoundation'Request');
    $requestMock
        ->expects($this->any())
        ->method('getLocale')
        ->will($this->returnValue('en'));
    $placesAutocompleteType = new PlacesAutocompleteType(
        $placesAutocompleteHelperMock,
        $requestMock
    );
    // Mock the FormType: entity
    $mockEntityManager = $this->getMockBuilder(''Doctrine'ORM'EntityManager')
        ->disableOriginalConstructor()
        ->getMock();
    $mockRegistry = $this->getMockBuilder('Doctrine'Bundle'DoctrineBundle'Registry')
        ->disableOriginalConstructor()
        ->getMock();
    $mockRegistry->expects($this->any())->method('getManagerForClass')
        ->will($this->returnValue($mockEntityManager));
    $mockEntityManager ->expects($this->any())->method('getClassMetadata')
        ->withAnyParameters()
        ->will($this->returnValue(new ClassMetadata('entity')));
    $repo = $this->getMockBuilder('Doctrine'ORM'EntityRepository')
        ->disableOriginalConstructor()
        ->getMock();
    $mockEntityManager ->expects($this->any())->method('getRepository')
        ->withAnyParameters()
        ->will($this->returnValue($repo));
    $repo->expects($this->any())->method('findAll')
        ->withAnyParameters()
        ->will($this->returnValue(new ArrayCollection()));

    $entityType = new EntityType($mockRegistry);

    return array(new PreloadedExtension(array(
        'places_autocomplete' => $placesAutocompleteType,
        'entity' => $entityType,
    ), array()));
}
}

希望这有帮助。让我知道。

这是

对@Matteo解决方案的补充,以防其他人遇到嘲笑EntityType依赖项的相同复杂性。 这让 QueryBuilder 默认调用 select(( 和 from(( 方法,这些方法反映了函数内核加载时发生的情况,并且在测试运行中丢失了(解析器返回"SELECT WHERE ..."(。 请注意,实体字段配置数组中的类值必须手写出来,例如 'class' => 'AcmeBundle'Entity'MyClass',而不是速记'class' => 'AcmeBundle:MyClass'只是为了模拟存储库。

...
use Doctrine'DBAL'Platforms'PostgreSqlPlatform;
use Doctrine'ORM'Configuration;
use Doctrine'ORM'Mapping'ClassMetadata;
use Doctrine'ORM'QueryBuilder;
use Symfony'Bridge'Doctrine'Form'Type'EntityType;
use Symfony'Component'Form'Extension'Core'CoreExtension;
use Symfony'Component'Form'Extension'Validator'Type'FormTypeValidatorExtension;
use Symfony'Component'Form'Forms;
use Symfony'Component'Form'PreloadedExtension;
use Symfony'Component'Form'Test'TypeTestCase;
use Symfony'Component'Validator'ConstraintViolationList;
class MyTypeCase extends TypeTestCase
{
    ...
    protected function getExtensions()
    {
        // mock entity manager
        $entityManager = $this->getMockBuilder(''Doctrine'ORM'EntityManager')
            ->disableOriginalConstructor()
            ->setMethods(array('getClassMetadata', 'getRepository'))
            ->getMock()
        ;
        // this method will be mocked specific to the class name when provided
        // by the mocked repository below - this can be generic here
        $entityManager->expects($this->any())
            ->method('getClassMetadata')
            ->will($this->returnValue(new ClassMetadata('entity')))
        ;
        $parent = $this;
        $entityManager->expects($this->any())
            ->method('getRepository')
            ->will($this->returnCallback(function($entityName) use ($parent) {
                // if ever the Doctrine'ORM'Query'Parser is engaged, it will check for
                // the existence of the fields used in the DQL using the class metadata
                $classMetadata = new ClassMetadata($entityName);
                if (preg_match('/[^a-z]MyClass$/i', $entityName)) {
                    $classMetadata->addInheritedFieldMapping(array('fieldName' => 'someField', 'columnName' => 'some_field'));
                    $classMetadata->addInheritedFieldMapping(array('fieldName' => 'anotherField', 'columnName' => 'another_field'));
                }
                // mock statement
                $statement = $parent->getMockBuilder(''Doctrine'DBAL'Statement')
                    ->disableOriginalConstructor()
                    ->getMock()
                ;
                // mock connection
                $connection = $parent->getMockBuilder(''Doctrine'DBAL'Connection')
                    ->disableOriginalConstructor()
                    ->setMethods(array('connect', 'executeQuery', 'getDatabasePlatform', 'getSQLLogger', 'quote'))
                    ->getMock()
                ;
                $connection->expects($parent->any())
                    ->method('connect')
                    ->will($parent->returnValue(true))
                ;
                $connection->expects($parent->any())
                    ->method('executeQuery')
                    ->will($parent->returnValue($statement))
                ;
                $connection->expects($parent->any())
                    ->method('getDatabasePlatform')
                    ->will($parent->returnValue(new PostgreSqlPlatform()))
                ;
                $connection->expects($parent->any())
                    ->method('quote')
                    ->will($parent->returnValue(''))
                ;
                // mock unit of work
                $unitOfWork = $parent->getMockBuilder(''Doctrine'ORM'UnitOfWork')
                    ->disableOriginalConstructor()
                    ->getMock()
                ;
                // mock entity manager
                $entityManager = $parent->getMockBuilder(''Doctrine'ORM'EntityManager')
                    ->disableOriginalConstructor()
                    ->setMethods(array('getClassMetadata', 'getConfiguration', 'getConnection', 'getUnitOfWork'))
                    ->getMock()
                ;
                $entityManager->expects($parent->any())
                    ->method('getClassMetadata')
                    ->will($parent->returnValue($classMetadata))
                ;
                $entityManager->expects($parent->any())
                    ->method('getConfiguration')
                    ->will($parent->returnValue(new Configuration()))
                ;
                $entityManager->expects($parent->any())
                    ->method('getConnection')
                    ->will($parent->returnValue($connection))
                ;
                $entityManager->expects($parent->any())
                    ->method('getUnitOfWork')
                    ->will($parent->returnValue($unitOfWork))
                ;
                // mock repository
                $repo = $parent->getMockBuilder(''Doctrine'ORM'EntityRepository')
                    ->setConstructorArgs(array($entityManager, $classMetadata))
                    ->setMethods(array('createQueryBuilder'))
                    ->getMock()
                ;
                $repo->expects($parent->any())
                    ->method('createQueryBuilder')
                    ->will($parent->returnCallback(function($alias) use ($entityManager, $entityName) {
                        $queryBuilder = new QueryBuilder($entityManager);
                        $queryBuilder->select($alias)
                            ->from($entityName, $alias)
                        ;
                        return $queryBuilder;
                    }))
                ;
                return $repo;
            }))
        ;
        // mock registry
        $registry = $this->getMockBuilder(''Doctrine'Bundle'DoctrineBundle'Registry')
            ->disableOriginalConstructor()
            ->setMethods(array('getManagerForClass'))
            ->getMock()
        ;
        $registry->expects($this->any())
            ->method('getManagerForClass')
            ->will($this->returnValue($entityManager))
        ;
        // build the extensions
        $extensions = new PreloadedExtension(
            array(
                'entity' => new EntityType($registry),
            ),
            array()
        );
        return array($extensions);
    }
}
这是

对@Matteo解决方案的补充 - 当你使用Mockery时,你可以得到EntityType:

$mockEntityManager = 'Mockery::mock(''Doctrine'ORM'EntityManager');
$mockRegistry = 'Mockery::mock('Doctrine'Bundle'DoctrineBundle'Registry');
$mockRegistry->shouldReceive('getManagerForClass')->andReturn($mockEntityManager);
$mockEntityManager->shouldReceive('getClassMetadata')->andReturn(new ClassMetadata('entity'));
$repo = 'Mockery::mock('Doctrine'ORM'EntityRepository');
$mockEntityManager->shouldReceive('getRepository')->andReturn($repo);
$repo->shouldReceive('findAll')->andReturn(new ArrayCollection());
$entityType = new EntityType($mockRegistry);