在Symfony 2 WebTestCase上创buildtesting数据库和加载装置的最佳方法是什么?

我有一个WebTestCase在我的应用程序中执行一些基本的路线。

我想在PHPUnit的setUp方法中创build一个和我的主数据库完全相同的testing数据库,然后在其中加载fixture。

我目前正在做一些解决方法,并执行一些控制台命令,如下所示:

 class FixturesWebTestCase extends WebTestCase { protected static $application; protected function setUp() { self::runCommand('doctrine:database:create'); self::runCommand('doctrine:schema:update --force'); self::runCommand('doctrine:fixtures:load --purge-with-truncate'); } protected static function runCommand($command) { $command = sprintf('%s --quiet', $command); return self::getApplication()->run(new StringInput($command)); } protected static function getApplication() { if (null === self::$application) { $client = static::createClient(); self::$application = new Application($client->getKernel()); self::$application->setAutoExit(false); } return self::$application; } } 

但是我确定这不是最好的方法,尤其是因为doctrine:fixtures:load期望用户点击Y字符来确认动作。

我该如何解决这个问题?

如果您想使用doctrine:fixtures:load ,则可以使用--append选项来避免用户确认。 由于您每次都重新创build数据库,因此不需要清除。 我曾经单独使用主义教具来进行testing,但是现在已经改用Fixtures & LiipFunctionalTestBundle来避免DRY。 这个捆绑使pipe理更容易pipe理。

编辑:大卫Jacquel的答案是正确的加载学说夹具:

 doctrine:fixtures:load --no-interaction or doctrine:fixtures:load -n 

为了绕过用户确认,您可以使用

 doctrine:fixtures:load --no-interaction or doctrine:fixtures:load -n 

更新的答案

您可以为您的testing用例创build一个基类,通过利用Doctrine Data Fixtures库中的一些类,使夹具加载变得容易。 这个类看起来非常像这样:

 <?php use Doctrine\Common\DataFixtures\Executor\ORMExecutor; use Doctrine\Common\DataFixtures\FixtureInterface; use Doctrine\Common\DataFixtures\Purger\ORMPurger; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; abstract class FixtureAwareTestCase extends KernelTestCase { /** * @var ORMExecutor */ private $fixtureExecutor; /** * @var ContainerAwareLoader */ private $fixtureLoader; public function setUp() { self::bootKernel(); } /** * Adds a new fixture to be loaded. * * @param FixtureInterface $fixture */ protected function addFixture(FixtureInterface $fixture) { $this->getFixtureLoader()->addFixture($fixture); } /** * Executes all the fixtures that have been loaded so far. */ protected function executeFixtures() { $this->getFixtureExecutor()->execute($this->getFixtureLoader()->getFixtures()); } /** * @return ORMExecutor */ private function getFixtureExecutor() { if (!$this->fixtureExecutor) { /** @var \Doctrine\ORM\EntityManager $entityManager */ $entityManager = self::$kernel->getContainer()->get('doctrine')->getManager(); $this->fixtureExecutor = new ORMExecutor($entityManager, new ORMPurger($entityManager)); } return $this->fixtureExecutor; } /** * @return ContainerAwareLoader */ private function getFixtureLoader() { if (!$this->fixtureLoader) { $this->fixtureLoader = new ContainerAwareLoader(self::$kernel->getContainer()); } return $this->fixtureLoader; } } 

然后,在你的testing案例中,简单地扩展上面的类,并在testing之前添加所有需要的灯具并执行它们。 这会在加载灯具之前自动清除你的数据库。 示例如下:

 class MyTestCase extends FixtureAwareTestCase { public function setUp() { parent::setUp(); // Base fixture for all tests $this->addFixture(new FirstFixture()); $this->addFixture(new SecondFixture()); $this->executeFixtures(); // Fixtures are now loaded in a clean DB. Yay! } } 

老解答

(我决定“弃用”这个答案,因为它只解释了如何清理数据库而不告诉如何加载灯具)。

有一个更干净的方式来完成这个,而不必运行命令。 它基本上是使用SchemaTool和ORMPurger的组合。 您可以创build一个抽象基类来执行这种操作,以避免为每个专门的testing用例重复这些操作。 下面是一个testing用例类的代码示例,它为通用testing用例设置数据库:

 use Doctrine\Common\DataFixtures\Purger\ORMPurger; use Doctrine\ORM\Tools\SchemaTool; abstract class DatabaseAwareWebTestCase extends WebTestCase { public static function setUpBeforeClass() { parent::setUpBeforeClass(); $kernel = static::createKernel(); $kernel->boot(); $em = $kernel->getContainer()->get('doctrine')->getManager(); $schemaTool = new SchemaTool($em); $metadata = $em->getMetadataFactory()->getAllMetadata(); // Drop and recreate tables for all entities $schemaTool->dropSchema($metadata); $schemaTool->createSchema($metadata); } protected function tearDown() { parent::tearDown(); $purger = new ORMPurger($this->getContainer()->get('doctrine')->getManager()); $purger->setPurgeMode(ORMPurger::PURGE_MODE_TRUNCATE); $purger->purge(); } } 

这样,在运行从上述类inheritance的每个testing用例之前,数据库模式将从头开始重build,然后在每次testing运行后清理。

希望这可以帮助。

我用这个命令:

 yes | php app/console doctrine:fixtures:load --purge-with-truncate 

但是当然LiipFunctionalTestBundle看起来很有前途。

我偶然发现了一个名为Doctrine-Test-Bundle的非常整齐的包,而不是在每个testing中创build和删除模式,它只是回滚。 我的testing从1分40秒到2秒。 它是孤立的。 所有你需要的是一个明确的testing数据库,它会做的伎俩。

我想加载所有的灯具像doctrine:fixtures:load命令呢。 我不想在testing用例中运行exec ,因为这似乎是一个混乱的做法。 我看了doctrine命令是如何做到这一点,只是复制在相关的行。

我从Symfony WebTestCase扩展,在创build内核之后,我只是调用我的方法,它的工作方式与Doctrine load-fixtures命令完全相同。

  /** * Load fixtures for all bundles * * @param Kernel $kernel */ private static function loadFixtures(Kernel $kernel) { $loader = new DataFixturesLoader($kernel->getContainer()); $em = $kernel->getContainer()->get('doctrine')->getManager(); foreach ($kernel->getBundles() as $bundle) { $path = $bundle->getPath().'/DataFixtures/ORM'; if (is_dir($path)) { $loader->loadFromDirectory($path); } } $fixtures = $loader->getFixtures(); if (!$fixtures) { throw new InvalidArgumentException('Could not find any fixtures to load in'); } $purger = new ORMPurger($em); $executor = new ORMExecutor($em, $purger); $executor->execute($fixtures, true); }