2010-12-06 10 views
37

Intenté encontrar algo sobre esto en Google pero no salió nada. Tengo una clase TestCase que hereda de WebTestCase, con algunos métodos que desea utilizar en todas mis pruebas de unidad/funcionales:Symfony 2 + Doctrine 2 + PHPUnit 3.5: Serialización de excepción de cierre

<?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); 
    } 
} 

Entonces, mi prueba de unidad:

<?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); 
} 
} 

que estaba trabajando antes , pero, de repente, después de que actualicé mis proveedores (doctrina incluido), comenzó a lanzar esta excepción:

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 

me he dado cuenta que el problema viene de la carga del accesorio. Si elimino el código que carga artefactos, funciona.

¿Alguien sabe qué podría estar mal en mi código? ¿Es esta la mejor forma de cargar accesorios?

Gracias!

Respuesta

86

No está técnicamente relacionado con el problema. Sin embargo, me fue muy difícil tratar de resolver el problema de "Serialización de 'Cierre' no permitido" al utilizar PHPUnit, y esta pregunta es el resultado más importante de Google.

El problema proviene del hecho de que PHPUnit serializa todos los $ GLOBALS en el sistema para realizar una copia de seguridad esencial mientras se ejecuta la prueba. Luego los restaura después de la prueba.

Sin embargo, si tiene cierres en su espacio GLOBAL, va a causar problemas. Hay dos formas de resolverlo.

Puede deshabilitar totalmente el procedimiento de copia de seguridad global mediante el uso de una anotación.

/** 
* @backupGlobals disabled 
*/ 
class MyTest extends PHPUnit_Framework_TestCase 
{ 
    // ... 
} 

O, si usted sabe qué variable está causando el problema (buscar una lambda en var_dump ($ GLOBALS)), que sólo puede lista negra la variable (s) problema.

class MyTest extends PHPUnit_Framework_TestCase 
{ 
    protected $backupGlobalsBlacklist = array('application'); 
    // ... 
} 
+1

¡Gracias por su respuesta! esto es de hecho lo que tuve que hacer para resolver la mayoría de mis problemas con esta excepción. El único problema que tengo aparentemente proviene del componente Validator de Symfony 2 en mis pruebas. Lamentablemente, no pude entender por qué sucede todavía. – Adrian

+0

Habría sido tan doloroso resolverlo solo. +1 para la respuesta útil – Rowan

+1

Esto parece haber sido resuelto en PHPUnit 3.6: https://github.com/sebastianbergmann/phpunit/pull/352 – scribu

4

También puedes intentarlo.

<phpunit backupGlobals="false"> 
    <testsuites> 
     <testsuite name="Test"> 
      <directory>.</directory> 
     </testsuite> 
    </testsuites> 
</phpunit>