我面临着ZF3和Doctrine的PHPUnit测试"连接太多"的问题,因为我每次PHPUnit执行大约200个测试。我已经找到了一些关于堆栈溢出的问题和答案,但这些问题和答案都不起作用。
我的设置:ZF2/ZF3、条令2和PHPUnit。
我有一个用于所有测试的基本测试类,setUp和tearDown函数如下所示:
public function setUp()
{
$this->setApplicationConfig(Bootstrap::getConfig());
Bootstrap::loadAllFixtures();
if (!static::$em) {
echo "init em";
static::$em = Bootstrap::getEntityManager();
}
parent::setUp();
....
}
public function tearDown()
{
parent::tearDown();
static::$em->flush();
static::$em->clear();
static::$em->getConnection()->close();
$refl = new ReflectionObject($this);
foreach ($refl->getProperties() as $prop) {
if (!$prop->isStatic() && 0 !== strpos($prop->getDeclaringClass()->getName(), 'PHPUnit_')) {
$prop->setAccessible(true);
$prop->setValue($this, null);
}
}
gc_collect_cycles();
}
public static function (Bootstrap::)loadAllFixtures()
{
static::$em->getConnection()->executeUpdate("SET foreign_key_checks = 0;");
$loader = new Loader();
foreach (self::$config['data-fixture'] as $fixtureDir) {
$loader->loadFromDirectory($fixtureDir);
}
$purger = new ORMPurger(static::$em);
$executor = new ORMExecutor(static::$em, $purger);
$executor->execute($loader->getFixtures());
$executor = null;
$purger = null;
static::$em->getConnection()->executeUpdate("SET foreign_key_checks = 1;");
static::$em->flush();
static::$em->clear();
}
我正在使用innotop监控我的本地MySQL服务器,连接数量正在增加。
你知道我遗漏了什么吗?
谢谢,Alexander
2017年2月14日更新:我已经将函数更改为使用static::$em
,并添加了Bootstrap::loadAllFixtures
方法。
如果我将static::$em->close()
添加到tearDown
方法中,则以下所有测试都将失败,并显示类似"EntityManager已关闭"的消息。echo "init em";
仅被调用一次,并显示用于第一次测试。是否可以检查我的应用程序是否打开连接而不关闭它们?我的测试用例基于AbstractHttpControllerTestCase
我也遇到了这个问题。根据PHPUnit文档中的建议,我做了以下操作:
final public function getConnection()
{
if ($this->conn === null) {
if (self::$pdo == null) {
//We get the EM from dependency injection container
$container = $this->getContainer();
self::$pdo = $container->get('Doctrine.EntityManager')->getConnection()->getWrappedConnection();
}
$this->conn = $this->createDefaultDBConnection(self::$pdo, 'spark_api_docker');
}
return $this->conn;
}
当self:$pdo
被共享时,当我在数据库中观察到show status like '%onn%';
时,"threads_connected"的数量逐渐增加,直到达到极限。
我找到了两个解决方案:
1)每次测试后关闭连接
public function tearDown()
{
parent::tearDown();
//You'll probably need to get hold of our entity manager another way
$this->getContainer()->get('Doctrine.EntityManager')->getConnection()->close();
}
重要的是,不要将self::$pdo
设置为null
。我在其他地方看到过这是一个建议,但将其设置为静态属性,然后在每次测试后重置它是没有意义的。
这可以关闭不再需要的连接。当测试用例完成时,除非您关闭了连接,否则它将保持打开状态,直到脚本结束(即PHPUnit完成运行测试)。由于您要为每个测试用例创建一个新的连接,所以连接的数量会增加。
2)在单独的PHP线程中运行每个测试
这是大锤式的方法。它可能会在某种程度上影响你的测试速度。在phpunit.xml`:中
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
...
processIsolation = "true"
>
...
</phpunit>
返回PHPUnit的建议,存储连接和PDO有助于避免为每个测试创建新连接,但在您有许多的测试用例时对您没有帮助。每个测试用例都在同一个线程中实例化,每个测试用例将创建一个新的连接。
您的tearDown方法看起来应该可以完成任务。我只是这样做,从未经历过这个问题
protected function tearDown()
{
parent::tearDown();
$this->em->close();
$this->em = null;
}
Bootstrap::loadAllFixtures方法做什么?是否有可能被忽略的数据库连接?