Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Environment specific data fixtures with Symfony+Doctrine

Tags:

With Smyfony2 and Doctrin2, data fixtures can be created using the following example: http://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html

What I would like is to be able to use this concept for testing so that setup/teardown can create a pure test data environment for functional testing. How might I go about having a specific set of test-only fixtures run during functional tests and how do I separate these fixtures from my standard fixtures so that the console command ignores them?

It seems that the way to do it would be to replicate the functionality of the doctrine:fixtures console command and store the test fixtures elsewhere. Does anyone have a better solution?

like image 419
Jason McClellan Avatar asked Aug 05 '12 16:08

Jason McClellan


1 Answers

An alternative to breaking out fixtures by directory is to use a custom fixture class. Your fixture classes would then extend this class and specify the environments it will actually be loaded in.

<?php

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\KernelInterface;

/**
 * Provides support for environment specific fixtures.
 *
 * This container aware, abstract data fixture is used to only allow loading in
 * specific environments. The environments the data fixture will be loaded in is
 * determined by the list of environment names returned by `getEnvironments()`.
 *
 * > The fixture will still be shown as having been loaded by the Doctrine
 * > command, `doctrine:fixtures:load`, despite not having been actually
 * > loaded.
 *
 * @author Kevin Herrera <[email protected]>
 */
abstract class AbstractDataFixture implements ContainerAwareInterface, FixtureInterface
{
    /**
     * The dependency injection container.
     *
     * @var ContainerInterface
     */
    protected $container;

    /**
     * {@inheritDoc}
     */
    public function load(ObjectManager $manager)
    {
        /** @var KernelInterface $kernel */
        $kernel = $this->container->get('kernel');

        if (in_array($kernel->getEnvironment(), $this->getEnvironments())) {
            $this->doLoad($manager);
        }
    }

    /**
     * {@inheritDoc}
     */
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    /**
     * Performs the actual fixtures loading.
     *
     * @see \Doctrine\Common\DataFixtures\FixtureInterface::load()
     *
     * @param ObjectManager $manager The object manager.
     */
    abstract protected function doLoad(ObjectManager $manager);

    /**
     * Returns the environments the fixtures may be loaded in.
     *
     * @return array The name of the environments.
     */
    abstract protected function getEnvironments();
}

Your fixtures would end up looking like this:

<?php

namespace Vendor\Bundle\ExampleBundle\DataFixtures\ORM;

use AbstractDataFixture;
use Doctrine\Common\Persistence\ObjectManager;

/**
 * Loads data only on "prod".
 */
class ExampleData extends AbstractDataFixture
{
    /**
     * @override
     */
    protected function doLoad(ObjectManager $manager)
    {
        // ... snip ...
    }

    /**
     * @override
     */
    protected function getEnvironments()
    {
        return array('prod');
    }
}

I believe that this should work with both ORM an ODM data fixtures.

like image 190
Kevin Herrera Avatar answered Sep 28 '22 03:09

Kevin Herrera