Search code examples
symfonydoctrine-ormphpunitfixturesliipfunctionaltestbundle

Symfony2 tests: Issue with fixtures and foreign keys


I'm developing a project with Symfony and Doctrine and I have an issue with my tests. I'm using Fixtures to load data for the tests, and some of my entities have associations between them. The first time I run my tests with empty DB tables the tests succeed flawlessly. But when I run the test once again, I got an error:

Doctrine\DBAL\DBALException: An exception occurred while executing 'DELETE FROM Ent':

SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (my_db.Ent, CONSTRAINT FK_FE5D1D1E727ACA70 FOREIGN KEY (parent_id) REFERENCES Ent (id))

The reason for the error is obvious: a row cannot be deleted when another row is referencing it though a foreign key.

If I manually truncate the table disabling foreign key constrains first and run the test again with an empty table, the tests are successful once again. But I have to repeat this every time I run the tests.

So the question is: is there a way to make Symfony or PHPUnit handle this automatically?

Thanks!

EDIT: I forgot to mention I'm using the Liip\FunctionalTestBundle\Test\WebTestCase class.


Solution

  • I ended up extending the WebTestCase as suggested by Nextar. Thanks!

    This is the code:

    <?php
    
    namespace Acme\MyBundle\Tests\Controller;
    
    use Liip\FunctionalTestBundle\Test\WebTestCase;
    
    class MyWebTestCase extends WebTestCase {
    
      protected function loadFixtures(array $classNames, $omName = null, $registryName = 'doctrine', $purgeMode = null) {
        $this->getContainer()->get('doctrine')->getManager()->getConnection()->query(sprintf('SET FOREIGN_KEY_CHECKS=0'));
        $result = parent::loadFixtures($classNames, $omName, $registryName, $purgeMode);
        $this->getContainer()->get('doctrine')->getManager()->getConnection()->query(sprintf('SET FOREIGN_KEY_CHECKS=1'));
        return $result;
      }
    }