dmaicher / doctrine-test-bundle

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

Using PDO results in error #287

Closed wnnawalaniec closed 4 months ago

wnnawalaniec commented 4 months ago

Not sure if bug, missing docs and this was expected but this bundle doesn't work with PDO, as PDO doesn't allow for nested transactions. Calling beginTransaction multiple times on same connection will result in exception. I created new Symfony 7 project, installed Doctrine bundle, Behat and this and in default config it won't work.

This happens because when StaticDriver connects for the first time it already starts new transaction, and then when test case begins in reaction to Behat event, BehatListener tries to begin another transaction.

dmaicher commented 4 months ago

nested transactions should be handled by Doctrine DBALs abstraction layer. It will use savepoints for that.

So yeah messing directly with PDO transactions will likely fail.

in reaction to Behat event, BehatListener tries to begin another transaction.

Can you point to the code that triggers this?

dmaicher commented 4 months ago

Ah you were talking about this?

https://github.com/dmaicher/doctrine-test-bundle/blob/46de5bbe451b9b635a3ae85a47d68cd1ff56bc1b/src/DAMA/DoctrineTestBundle/Behat/BehatListener.php#L37

in the test suite of this bundle it works fine. There shouldn't be any double transaction start.

Can you provide a reproducer for that issue?

wnnawalaniec commented 4 months ago

Oh, I've found the issue but it took me some time, sorry. If you have DATABASE_URL like this: DATABASE_URL="mysql://test:test@127.0.0.1:7000/test?serverVersion=16&charset=utf8" All works fine. But, if you remove serverVersion it stops working: DATABASE_URL="mysql://test:test@127.0.0.1:7000/test?charset=utf8" I've created simple project with all bundles setup here https://github.com/wnnawalaniec/dama-test-issue, nothing special...

The reason for this is, that when setNestTransactionsWithSavepoints is called and platform is unknow doctrine will try to find out what server is used to check if nested transactions are supported, and to do this it connect to database. When it does, then the transaction begins due to StaticDriver starting it. Then when behat event is raised, this listener tries to begin yet another transaction which failes.

When we provide with serverVersion there is no connection made and $connections at StaticDriver is empty, therefor when this behat listener is begining transaction nothing happens. Then on first connection made in our code, StaticDriver starts new static connection and begin transaction only once.

Still not sure if it's this lib issue or doctrine stuff...

dmaicher commented 4 months ago

Hm interesting. Thanks for investigating @wnnawalaniec. I'm struggling to understand why this issue does not happen in the testsuite of the bundle however. There we also have a connection without server version and so it should also run this code to detect the platform.

I will try to dig into it a bit more.

dmaicher commented 4 months ago

Ok so I think this might have something todo with the fact that you are injecting the connection service into your context.

https://github.com/wnnawalaniec/dama-test-issue/blob/32bf6a1bb7b72651457c81ccfa6efdb16e034eb0/tests/Behat/DemoContext.php#L28

So the connection is initialized before we even run the hook that will do StaticDriver::beginTransaction()?

Does it work if you remove that injected connection service?

wnnawalaniec commented 4 months ago

Yes it does

dmaicher commented 4 months ago

Ok so I don't see any way around this. The connection should not be used or initialized before that hook is run.

But you have a workaround for now by setting the server version.