PHPUnit 测试和 Doctrine,连接太多

标签 php zend-framework doctrine-orm zend-framework2 doctrine

对于 ZF3 和 Doctrine 的 PHPUnit 测试,我面临着“太多连接”的问题,因为我在每次 PHPUnit 执行时执行约 200 个测试。 我已经找到了一些关于堆栈溢出的问题和答案,但这些都不起作用。

我的设置: ZF2/ZF3、Doctrine 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 服务器,并且连接数在增加。

你知道我遗漏了什么吗?

谢谢, 亚历山大

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 被共享时,'threads_connected' 的数量,当我观察到 show status like '%onn%'; 在我的数据库上时,爬行直到达到极限为止。

我找到了两个解决方案:


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 有助于避免为每个测试 创建新的连接,但当您有许多测试用例 时则无济于事。每个测试用例都在同一个线程中实例化,每个都将创建一个新连接。

关于PHPUnit 测试和 Doctrine,连接太多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42188033/

相关文章:

php - Zend - 如何在 session 表上启用缓存(元数据)?

PHP JS 将日期转换为用户时区

php - zend framework 中存储的实例化对象在哪里?

php - 使用 fetchcolumn() while 循环在 pdo 中无法正常工作后

文档根目录内部或外部的 PHP 库?

mysql - 是否可以通过主键的一部分对 DQL 查询进行分组并返回具有 max() 日期时间记录(早于引用日期)的记录?

mysql - Doctrine/Symfony 更改单个列的字符集

php - 使用 LEFT JOIN 的 Doctrine 2 UPDATE

javascript - jQuery 和 PHP : Calculate the sum and send it back to client

php - 将反斜杠分隔的字符串转换为关联数组