I'm writing integration/database tests for a Zend Framework 3 application by using
- zendframework/zend-test
3.1.0
, - phpunit/phpunit
6.2.2
, and - phpunit/dbunit
3.0.0
My tests are failing due to the
Connect Error: SQLSTATE[HY000] [1040] Too many connections
I set some breakpoints and took a look into the database:
SHOW STATUS WHERE `variable_name` = 'Threads_connected';
And I've actually seen over 100
opened connections.
I've reduced them by disconnecting in the tearDown()
:
protected function tearDown()
{
parent::tearDown();
if ($this->dbAdapter && $this->dbAdapter instanceof Adapter) {
$this->dbAdapter->getDriver()->getConnection()->disconnect();
}
}
But I still have over 80
opened connections.
How to decrease the number of the database connections in tests to a possible minimum?
more info
(1) I have a lot of tests, where I dispatch
a URI. Every such request causes at least one database request, that cause a new database connection. These connections seem not to be closed. This might cause the most connections. (But I haven't yet found a way to make the application close the connections after the request is processed.)
(2) One of the issues might be my testing against the database:
protected function retrieveActualData($table, $idColumn, $idValue)
{
$sql = new Sql($this->dbAdapter);
$select = $sql->select($table);
$select->where([$table . '.' . $idColumn . ' = ?' => $idValue]);
$statement = $sql->prepareStatementForSqlObject($select);
$result = $statement->execute();
$data = $result->current();
return $data;
}
But the call of the $this->dbAdapter->getDriver()->getConnection()->disconnect()
before the return
gave nothing.
Example of usage in a test method:
public function testInputDataActionSaving()
{
// The getFormParams(...) returns an array with the needed input.
$formParams = $this->getFormParams(self::FORM_CREATE_CLUSTER);
$createWhateverUrl = '/whatever/create';
$this->dispatch($createWhateverUrl, Request::METHOD_POST, $formParams);
$this->assertEquals(
$formParams['whatever']['some_param'],
$this->retrieveActualData('whatever', 'id', 2)['some_param']
);
}
(3) Another issue might be in the PHPUnit (or my configuration of it?). (Striken out, because "PHPUnit does not do anything related to database connections.", see this comment.) Anyway, even if it's not a PHPUnit issue, the fact is, that after the line
$testSuite = $configuration->getTestSuiteConfiguration($this->arguments['testsuite'] ?? null);
in the PHPUnit\TextUI\Command
I get 31
new connections.
retrieveActualData()
is used to verify something, because it doesn't seem to test anything.) – SportytestInputDataActionSaving()
in the question. Thanks. – Astrometry--process-isolation
. It will close all connection after each test. – Conch$ vendor/phpunit/phpunit/phpunit --process-isolation --no-coverage --configuration ./phpunit.xml
). The execution breaks off with an errorNotice: Exception: Serialization of 'Closure' is not allowed in /var/www/.../my-project/vendor/phpunit/phpunit/src/Util/GlobalState.php:170
. ThebackupGlobals
is set tofalse
and theBootstrap
doesn't contain any closures. – Astrometry@runInSeparateProcess
annotation. The same error. – Astrometrydispatch()
method that you call intestInputDataActionSaving()
, the framework is being booted (including creating a database connection). It looks like this happens for every test class. Can you check how many connections you get if you run a single test class with, say, 10 tests (meaning 10 calls to dispatch). Then add or remove a test and see how the number of connections changes. – Sporty$db->closeConnection();
or in your case$this->dbAdapter->closeConnection();
? – NonfictionZend_Db
provided this method. But now there is no methodcloseConnection()
inZend\Db\Adapter\AdapterInterface
or in my concrete case inZend\Db\Adapter\Adapter
. Anyway, I tried$dbAdapter->getDriver()->getConnection()->disconnect();
instead, but it hasn't helped. – Astrometry$dbAdapter
manually or is it managed by the framework? When you are closing connection with$dbAdapter->getDriver()->getConnection()->disconnect();
: __destruct or shutdown function? You should add some extra logging when new connection is being created and while disconnecting. In your case I think you app is unable to close connection because of running queries. – Hutt$dbAdapter
provided by theMVC
ServiceManager
($container->get('Zend\Db\Adapter\Adapter'
). Yes, I also guess, that the problem is caused by the application and that it simply doesn't close the connection. But I don't see a way to force it to do that. – Astrometryn+1
only starts after the test numbern
is completed. And a test is completed, when the whole code of its method is executed. That means, when the responses have come back from the application. That means, when all requests of the requestn
are completed. I've also debugged a bit and saw, that it's working this way. – Astrometry