Dan*_*iro 64 tdd doctrine symfony
我有一个WebTestCase,它在我的应用程序中执行一些基本路由.
我想,在setUpPHPUnit 的方法中,创建一个与我的主数据库相同的测试数据库,并将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;
}
}
Run Code Online (Sandbox Code Playgroud)
但我很确定这不是最好的方法,特别是因为doctrine:fixtures:load期望用户点击一个Y字符来确认操作.
我怎么解决这个问题?
Dav*_*uel 35
为了绕过用户确认,您可以使用
doctrine:fixtures:load --no-interaction
or
doctrine:fixtures:load -n
Run Code Online (Sandbox Code Playgroud)
Mik*_*ike 34
如果要使用doctrine:fixtures:load,可以使用该--append选项来避免用户确认.由于每次都在重新创建数据库,因此不需要进行清除.我曾经单独使用doctrine fixtures进行测试,但后来改用了fixture和LiipFunctionalTestBundle来避免DRY.该捆绑包使夹具更易于管理.
编辑:David Jacquel的答案是加载Doctrine Fixtures的正确答案:
doctrine:fixtures:load --no-interaction
or
doctrine:fixtures:load -n
Run Code Online (Sandbox Code Playgroud)
And*_*ega 33
您可以为测试用例创建一个基类,通过利用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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在您的测试用例中,只需扩展上面的类,然后在测试之前添加所有需要的fixture并执行它们.这将在加载灯具之前自动清除数据库.示例如下:
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!
}
}
Run Code Online (Sandbox Code Playgroud)
(我决定"弃用"这个答案,因为它只解释了如何清理数据库而不告诉如何加载夹具).
有一个更简洁的方法来实现这一点,而无需运行命令.它基本上包括使用SchemaTool和ORMPurger的组合.您可以创建一个抽象基类来执行此类操作,以避免为每个专门的测试用例重复它们.下面是一个测试用例类的代码示例,它为通用测试用例设置数据库:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
这样,在运行继承自上述类的每个测试用例之前,将从头开始重建数据库模式,然后在每次测试运行后进行清理.
希望这可以帮助.
我偶然发现了一个名为Doctrine-Test-Bundle的非常简洁的软件包, 而不是在每个测试中创建和删除模式,而只是简单地回滚.我的测试从1分40秒到2分钟.它是孤立的.您所需要的只是一个清晰的测试数据库,它可以解决问题.