Symfony 2 + Doctrine 2 + PHPUnit 3.5:闭包异常的序列化

Adr*_*ian 38 phpunit doctrine symfony

我试图在谷歌上找到一些关于此的东西,但没有任何结果.我有一个继承自WebTestCase的TestCase类,我希望在所有单元/功能测试中使用一些方法:

<?php

namespace Application\FaxServerBundle\Test;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Doctrine\Common\DataFixtures\Loader;
use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;

use Application\FaxServerBundle\DataFixtures\ORM\NetworkConfigurationData;

class TestCase extends WebTestCase
{
    protected $kernel;

    public function setUp()
    {
        parent::setUp();
    }

    public function getEm()
    {
        return $this->getService( 'doctrine.orm.entity_manager' );
    }

    public function getNetworkConfigurationRepository()
    {
        return $this->getEm()->getRepository( 'Application\FaxServerBundle\Entity\NetworkConfiguration' );
    }

    public function loadNetworkConfigurationFixtures()
    {
        $loader = new Loader();
        $loader->addFixture( new NetworkConfigurationData() );

        $this->loadFixtures( $loader );
    }

    public function loadFixtures( $loader )
    {
        $purger     = new ORMPurger();
        $executor   = new ORMExecutor( $this->getEm(), $purger );
        $executor->execute( $loader->getFixtures() );
    }

    protected function getService( $name, $kernel = null )
    {
        return $this->getBootedKernel()->getContainer()->get( $name );
    }

    protected function hasService( $name, $kernel = null )
    {

        return $this->getBootedKernel()->getContainer()->has( $name );
    }

    protected function getBootedKernel()
    {
        $this->kernel = $this->createKernel();

        if ( !$this->kernel->isBooted() ) 
        {
            $this->kernel->boot();
        }

        return $this->kernel;
    }

    public function generateUrl( $client, $route, $parameters = array() )
    {
        return $client->getContainer()->get( 'router' )->generate( $route, $parameters );
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,我的单元测试:

<?php

namespace Application\FaxServerBundle\Tests\Entity;

use Doctrine\ORM\AbstractQuery;

use Application\FaxServerBundle\Entity;
use Application\FaxServerBundle\Test\TestCase;

class NetworkConfigurationRepositoryTest extends TestCase
{
 public function setUp()
 {
  parent::setUp();

  $this->loadNetworkConfigurationFixtures();
 }

 public function testGetConfiguration()
 {
  $config = $this->getNetworkConfigurationRepository()->getConfigurationArray();

  $this->assertInternalType( 'array', $config );
  $this->assertEquals( 6, count( $config ) );
  $this->assertArrayHasKey( 'id', $config );
  $this->assertArrayHasKey( 'ip', $config );
  $this->assertArrayHasKey( 'gateway', $config );
  $this->assertArrayHasKey( 'subnetMask', $config );
  $this->assertArrayHasKey( 'primaryDns', $config );
  $this->assertArrayHasKey( 'secondaryDns', $config );
 }

 public function testGetConfigurationObject()
 {
  $config = $this->getNetworkConfigurationRepository()->getConfigurationObject();

  $this->assertInternalType( 'object', $config );
 }

 public function testGetConfigurationArray()
 {
  $config = $this->getNetworkConfigurationRepository()->getConfigurationArray();

  $this->assertInternalType( 'array', $config );
 }
}
Run Code Online (Sandbox Code Playgroud)

它之前正在工作,但是,突然之后,在我更新了我的供应商(包括学说)之后,它开始抛出这个异常:

3) Application\FaxServerBundle\Tests\Entity\NetworkConfigurationRepositoryTest::testGetConfigurationArray
RuntimeException: PHP Fatal error:  Uncaught exception 'PDOException' with message 'You cannot serialize or unserialize PDO instances' in -:32
Stack trace:
#0 [internal function]: PDO->__sleep()
#1 -(32): serialize(Array)
#2 -(113): __phpunit_run_isolated_test()
#3 {main}

Next exception 'Exception' with message 'Serialization of 'Closure' is not allowed' in -:0
Stack trace:
#0 -(0): serialize()
#1 -(113): __phpunit_run_isolated_test()
#2 {main}
  thrown in - on line 0
Run Code Online (Sandbox Code Playgroud)

我发现问题来自夹具装载.如果我删除加载灯具的代码,它的工作原理.

有谁知道我的代码中可能有什么问题?这是加载灯具的最佳方式吗?

谢谢!

小智 89

在技​​术上与您的问题无关.但是,在使用PHPUnit时,我很难尝试解决"关闭'序列化'不允许"的问题,而这个问题是谷歌的最高结果.

问题来自于PHPUnit在测试运行时将系统中的所有$ GLOBAL序列化为必要的备份.然后在测试完成后恢复它们.

但是,如果您的GLOBAL空间中有任何闭包,则会导致问题.有两种方法可以解决它.

您可以使用注释完全禁用全局备份过程.

/**
 * @backupGlobals disabled
 */
class MyTest extends PHPUnit_Framework_TestCase
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您知道哪个变量导致了问题(在var_dump($ GLOBALS)中查找lambda),您可以将问题变量列入黑名单.

class MyTest extends PHPUnit_Framework_TestCase
{
    protected $backupGlobalsBlacklist = array('application');
    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • 这也可以通过命令开关`phpunit --no-globals-backup`(http://www.phpunit.de/manual/3.6/en/textui.h​​tml)或通过`中的相应属性来完成所有测试. phpunit.xml` file` <phpunit backupGlobals ="false"/>`(http://www.phpunit.de/manual/3.6/en/appendixes.configuration.html#appendixes.configuration.phpunit). (12认同)
  • 另外*避免*** - process-isolation**选项,它导致"不允许'序列化'闭包'".用PHPUnit 3.7测试 (9认同)
  • 我遇到了一个与 `--process-isolation` 相关的问题 - 看起来 PHPUnit 也尝试序列化通过数据提供程序传入的对象,即使你使用 `--no-globals-backup 也无法阻止它`. 我不得不重新设计我的数据提供程序并进行测试以解决这个问题。 (2认同)