PHPUnit测试和Doctrine,连接太多

时间:2017-02-12 13:18:39

标签: 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服务器,并且连接数正在增加。

你有什么我缺少的想法吗?

谢谢你, 亚历山大

更新14.02.2017: 我已将功能更改为使用static::$em并添加了Bootstrap::loadAllFixtures方法。

如果我将static::$em->close()添加到tearDown方法,则所有后续测试都会失败,并显示“EntityManager已关闭”等消息。 echo "init em";只调用一次并显示第一次测试。 是否有可能检查我的应用程序是否打开连接而不关闭它们?我的测试用例基于AbstractHttpControllerTestCase

2 个答案:

答案 0 :(得分:0)

你的tearDown方法看起来应该可以解决问题。我这样做,从未遇到过这个问题

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

    $this->em->close();
    $this->em = null; 
}

Bootstrap :: loadAllFixtures方法有什么作用?那里有没有可能被忽视的数据库连接?

答案 1 :(得分:0)

我也遇到了这个问题。按照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有助于避免为每个 test 创建新连接,但是当您有许多 test用例时,则无济于事。每个测试用例都在同一线程中实例化,并且每个将创建一个新的连接。