简体   繁体   English

PHPUnit测试和Doctrine,连接太多

[英]PHPUnit tests and Doctrine, too many connections

I'm facing problems with "too many connections" for PHPUnit tests for ZF3 and Doctrine, because I'm executing ~200 tests per PHPUnit execution. 对于ZF3和Doctrine的PHPUnit测试,我面临着“连接太多”的问题,因为我每次执行PHPUnit时都要执行~200次测试。 I've already found some questions and answers on stack overflow but non of these work. 我已经发现了一些关于堆栈溢出的问题和答案,但没有这些工作。

My setup: ZF2/ZF3, Doctrine 2 and PHPUnit. 我的设置:ZF2 / ZF3,Doctrine 2和PHPUnit。

I have a base test class for all tests and the setUp and tearDown function look like this: 我有一个基础测试类用于所有测试,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();
}

I'm monitoring my local MySQL server with innotop and the number of connections is increasing. 我正在使用innotop监视我的本地MySQL服务器,并且连接数量正在增加。

Do you have any ideas what I'm missing? 你有什么想法我错过了吗?

Thank you, Alexander 谢谢你,亚历山大

Update 14.02.2017: I've changed functions to use static::$em and added Bootstrap::loadAllFixtures method. 更新14.02.2017:我已将函数更改为使用static::$em并添加了Bootstrap::loadAllFixtures方法。

If I add static::$em->close() to tearDown method, all following test fail with message like "EntityManager already closed". 如果我将static::$em->close()tearDown方法,则所有后续测试都会失败,并显示“EntityManager已关闭”等消息。 echo "init em"; is only call once and shown for the first test. 只调用一次并显示第一次测试。 Is there a possibility to check if my Application opens connections without closing them? 是否有可能检查我的应用程序是否打开连接而不关闭它们? My test cases are based on AbstractHttpControllerTestCase 我的测试用例基于AbstractHttpControllerTestCase

Your tearDown method looks like it should do the trick. 你的tearDown方法看起来应该可以解决问题。 I just do this and have never experienced this issue 我这样做,从未遇到过这个问题

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

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

What does Bootstrap::loadAllFixtures method do? Bootstrap :: loadAllFixtures方法有什么作用? Is there any db connection in there that might be being overlooked? 那里有任何数据库连接可能被忽略了吗?

I came across this problem too. 我也遇到过这个问题。 Following the advice in PHPUnit's documentation I had done the following: 按照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;
}

While self:$pdo was being shared, the number of 'threads_connected', when I observed show status like '%onn%'; self:$pdo被共享时,'threads_connected'的数量,当我观察到show status like '%onn%'; on my database, crept up until it reached the limit. 在我的数据库上,一直爬到它的极限。

I found two solutions to this: 我找到了两个解决方案:


1) Close the connection after each test 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();
}

importantly, do not set self::$pdo to null . 重要的是,不要将self::$pdo设置为null I had seen this as a recommendation elsewhere, but there's no point setting it as a static property and then resetting it after each test. 我曾在其他地方看到过这个建议,但没有必要将它设置为静态属性,然后在每次测试后重置它。

This works my closing connections that are no longer needed. 这可以解决我不再需要的关闭连接。 When a testcase is finished, unless you have closed the connection it will remain open until the script ends (ie PHPUnit finishes running your test). 测试用例完成后,除非您已关闭连接,否则它将保持打开状态直到脚本结束(即PHPUnit完成运行测试)。 Since you're creating a new connection for each test case, the number of connections goes up. 由于您要为每个测试用例创建新连接,因此连接数会增加。


2) Run each test in a seperate PHP thread 2)在单独的PHP线程中运行每个测试

This is the sledgehammer approach. 这是大锤的方法。 It will likely impact the speed of your tests to one degree or another. 它可能会在一定程度上影响您的测试速度。 In your phpunit.xml`: 在你的phpunit.xml`中:

<?xml version="1.0" encoding="UTF-8"?>

<phpunit
    ...
    processIsolation = "true"
    >
    ...
</phpunit>

Returning to PHPUnit's advice, storing the connection and PDO helps with not creating new connections for each test but does not help you when you have many test cases . 回到PHPUnit的建议,存储连接和PDO有助于不为每个测试创建新的连接,但是当你有很多测试用例时却没有帮助。 Each test case gets instantianted in the same thread, and each will create a new connection. 每个测试用例都在同一个线程中实例化,每个测试用例都会创建一个新连接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM