Symfony FormType beaucoup de test avec EntityType

j'ai une question à poser à Symfony FormType testing. http://symfony.com/doc/current/cookbook/form/unit_testing.html

dans ma forme tape le entity le type est courant. Tester les types de forme avec un type de forme d'entité de doctrine est horrible.

C'est mon champ de formulaire.

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('products', 'entity', array(
        'class'     => 'AcmeDemoBundle:Product',
        'label'     => 'Product',
        'property'  => 'name',
        'required'  => false,
        'mapped'    => true,
        'multiple'  => true,
        'expanded'  => true
    ));
}

Et voici la simulation pour le terrain.

private function getEntityTypeMock()
{
    $entityRepositoryMock = $this->getMockBuilder('DoctrineORMEntityRepository')
        ->disableOriginalConstructor()
        ->getMock()
    ;

    $entityRepositoryMock->expects($this->once())
        ->method('findAll')
        ->will($this->returnValue(array()));

    $classMetaDataMock = $this->getMockBuilder('DoctrineORMMappingClassMetadata')
        ->disableOriginalConstructor()
        ->getMock();

    $mockEntityManager = $this->getMockBuilder('DoctrineORMEntityManager')
        ->disableOriginalConstructor()
        ->getMock();

    $mockEntityManager->expects($this->any())
        ->method('getClassMetadata')
        ->will($this->returnValue($classMetaDataMock));

    $mockEntityManager->expects($this->once())
        ->method('getRepository')
        ->will($this->returnValue($entityRepositoryMock));

    $mockRegistry = $this->getMockBuilder('DoctrineBundleDoctrineBundleRegistry')
        ->disableOriginalConstructor()
        ->getMock();

    $mockRegistry->expects($this->any())
        ->method('getManagerForClass')
        ->will($this->returnValue($mockEntityManager));

    $mockEntityType = $this->getMockBuilder('SymfonyBridgeDoctrineFormTypeEntityType')
        ->setMethods(array('getName'))
        ->setConstructorArgs(array($mockRegistry))
        ->getMock();

    $mockEntityType->expects($this->any())->method('getName')
        ->will($this->returnValue('entity'));

    return $mockEntityType;
}

Est-ce vraiment la bonne façon? À l'intérieur de l' TypeTestCase Je n'ai accès à rien, aucun conteneur Non noyau, rien. Cela fait tester un type de forme assez dur et frustant.

Est-il une meilleure façon de tester les types de formulaire? Ou une façon plus facile de traiter les types qui ont une dépendance ORM?

Cheers.

15
demandé sur createproblem 2014-06-06 14:50:10

1 réponses

j'ai eu du mal à tester à l'unité quelque chose qui dépend beaucoup d'un container de service. Au début, j'ai essayé de me moquer de tout, comme toi. Cela peut faire passer un test d'unité avec grand effort (les services ont tendance à compter sur d'autres services encore à Symfony, qui devra également être moqué), mais il faut encore plus d'efforts pour s'assurer que la réussite du test signifie qu'il fonctionnerait avec les données que vous voulez qu'il fonctionne avec.

en outre, l'unité testant une base de données est notoirement difficile et rarement abordée. Je ne suis pas sûr que ce que je partage est la "meilleure" réponse, mais c'est une réponse qui a fonctionné pour moi et il aide à l'unité tester les services réels. En tant que telle, j'ai trouvé que c'était une méthode plus efficace de tester que de se moquer des services.

ceci est basé sur un excellent article, que, bien sûr, je ne peux pas trouver maintenant (je le mettrai à jour si je le trouve pour les créditer).

en gros, vous pouvez configurer vos paquets pour avoir des conteneurs dans test.

compositeur.json:

"require-dev": {
    "sensio/framework-extra-bundle": ">=3.0",
    "symfony/asset": ">=3.2"
}

alors créez un config.yml avec tous les services dont vous pourriez avoir besoin et le strict minimum pour les formes Symfony:

framework:
    secret: 'shh'
    form: ~
    validation: { enable_annotations: true }
    session:
        storage_id: session.storage.mock_file

doctrine:
    # your doctrine settings if you want to test against the DB

créer une classe AppKernel.

class AppKernel extends Kernel
{
    public function registerBundles()
    {
        return array(
            new FrameworkBundle(),
            new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
            // any other bundles you need
        );
    }

    public function registerContainerConfiguration(LoaderInterface $loader)
    {
        $loader->load(__DIR__.'/config.yml');

    }

    public function getLogDir()
    {
        return '/tmp/log/' . $this->environment;
    }
}

enfin, je crée une classe helper dans mon TestCase de base:

protected function getContainer()
{
    if (!isset($this->kernel)) {
        $this->kernel = new AppKernel('test', true);
        $this->kernel->boot();
    }
    if (!isset($this->container)) {
        $this->container = $this->kernel->getContainer();
    }
    return $this->container;
}

vous pouvez Maintenant accéder à tous les services que vous avez enregistrés comme ceci:

public function testContainerAccess()
{
    $this->assertTrue(is_object($this->getContainer());
    $this->assertTrue($this->getContainer()->get('doctrine.orm.entity_manager') instanceof \Doctrine\ORM\EntityManagerInterface);
}

tester sur une base de données est toujours délicat et est une boîte de Pandore séparée. Dans ce cas, la chose la plus facile à faire serait probablement de créer un schéma de test séparé et d'exécuter vos requêtes par rapport à cela.

J'espère que cela vous aidera.

3
répondu smcjones 2017-12-22 16:10:48