dmaicher / doctrine-test-bundle

Symfony bundle to isolate your app's doctrine database tests and improve the test performance
MIT License
1.08k stars 61 forks source link

Invalid savepoint specification: 7 ERROR: no such savepoint #134

Closed oenie closed 4 years ago

oenie commented 4 years ago

Hi,

I introduced this poackage into our Symfony application while migrating to Symfony 4. Everything has been running fine, but right now I'm running into a peculiar problem.

I am simply trying to inject an existing dependency into another class through constructor injection. This has been done in another class before (so it's not as if the class in question is new)

However, when I inject it into my modified class, my tests start failing: Doctrine\DBAL\Driver\PDOException: SQLSTATE[3B001]: Invalid savepoint specification: 7 ERROR: no such savepoint

I debugged this by just doing a print_r in the DBAL PDOConnection (we're using Postgres) And I'm noticing that he is trying to Rollback a Doctrine SAVEPOINT that looks like it has not been set.

   SET NAMES 'UTF8'
   SET NAMES 'UTF8'
   SET NAMES 'UTF8'
   RELEASE SAVEPOINT DOCTRINE2_SAVEPOINT_2
   ROLLBACK TO SAVEPOINT DOCTRINE2_SAVEPOINT_2

Any ideas why this might be happening ? Used packages for doctrine and this one:

    "php": ">=7.2.0",
    "symfony/symfony": "4.4.4",
    "doctrine/orm": "2.7.1",
    "doctrine/dbal": "2.10.1",
    "doctrine/doctrine-bundle": "2.0.7",

"require-dev": 
    "theofidry/alice-data-fixtures": "1.1.1",
    "phpunit/phpunit": "7.5.11",
    "doctrine/doctrine-fixtures-bundle": "3.3.0",
    "dama/doctrine-test-bundle": "6.4",
    "phpstan/phpstan-symfony": "^0.12.7"

I noticed the issue https://github.com/dmaicher/doctrine-test-bundle/issues/58 but that doesn't seem related at first sight. I have no knowledge of ALTER/... statements being run beforehand.

Any pointers ?

oenie commented 4 years ago

If i remove the dependency injection from the class altogether, everything works fine, and only savepoints that have previously been created are released:

SET NAMES 'UTF8'
SET NAMES 'UTF8'
SAVEPOINT DOCTRINE2_SAVEPOINT_2
SAVEPOINT DOCTRINE2_SAVEPOINT_3
RELEASE SAVEPOINT DOCTRINE2_SAVEPOINT_3
SAVEPOINT DOCTRINE2_SAVEPOINT_3
RELEASE SAVEPOINT DOCTRINE2_SAVEPOINT_3
ROLLBACK TO SAVEPOINT DOCTRINE2_SAVEPOINT_2
SET NAMES 'UTF8'    
SAVEPOINT DOCTRINE2_SAVEPOINT_2
SAVEPOINT DOCTRINE2_SAVEPOINT_3
RELEASE SAVEPOINT DOCTRINE2_SAVEPOINT_3
SAVEPOINT DOCTRINE2_SAVEPOINT_3
RELEASE SAVEPOINT DOCTRINE2_SAVEPOINT_3
SAVEPOINT DOCTRINE2_SAVEPOINT_3
RELEASE SAVEPOINT DOCTRINE2_SAVEPOINT_3
SAVEPOINT DOCTRINE2_SAVEPOINT_3
SAVEPOINT DOCTRINE2_SAVEPOINT_4
RELEASE SAVEPOINT DOCTRINE2_SAVEPOINT_4

etc.

dmaicher commented 4 years ago

Can you provide me with a bit more details?

oenie commented 4 years ago

Well, the thing is that just ALL of our test fail when I introduce the dependency:

Query causing the failure: RELEASE SAVEPOINT DOCTRINE2_SAVEPOINT_2

Doctrine\DBAL\Driver\PDOException: SQLSTATE[3B001]: Invalid savepoint specification: 7 ERROR: no such savepoint

/srv/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:54 /srv/vendor/dama/doctrine-test-bundle/src/DAMA/DoctrineTestBundle/Doctrine/DBAL/StaticConnection.php:57 /srv/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:1415 /srv/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:1299 /srv/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:1330 /srv/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:524 /srv/vendor/ACME/TestCase/Base/BaseTestCase.php:58

In our BaseTestCase class, we have e setup method as follows:

protected function setUp()
{
    parent::setUp();

    self::$client = static::createClient();
    $this->preserveDbState = self::$client->getContainer()->getParameter('test_preserve_db_state_tests');
    self::$em = self::$client->getContainer()->has('doctrine.orm.entity_manager') ? self::$client->getContainer()->get('doctrine.orm.entity_manager'): null;

    if ($this->preserveDbState == true) {
        self::$em->getConnection()->setAutoCommit(false);
        self::$em->beginTransaction();
    }
}

It's just the calling of that beginTransaction() that causes everything.

oenie commented 4 years ago

As mentioned before, whenever I don't add the dependency to our constructor, a SAVEPOINT DOCTRINE2_SAVEPOINT_2 is run at the point of self::$em->beginTransaction()

If I add the dependency that SAVEPOINT is never set, but it is tried to release it through RELEASE SAVEPOINT DOCTRINE2_SAVEPOINT_2

dmaicher commented 4 years ago

wondering why you need this?

if ($this->preserveDbState == true) {
    self::$em->getConnection()->setAutoCommit(false);
    self::$em->beginTransaction();
}

I mean that's what this bundle will take care of? It will roll-back any changes after a test.

Not quite sure yet what causes your problem. I would need some way of reproducing that issue :confused:

oenie commented 4 years ago

OK, I've been looking into our own code. Not sure why all of this is happening either. At first glance it looks like it is located there, although nothing has changed. I suppose this is a non-issue in this module. If I happen to find the exact reason I'll get back.

dmaicher commented 4 years ago

Closing for now. We can re-open if there is some way of reproducing it