2010-12-06 47 views
37

J'ai essayé de trouver quelque chose à ce sujet sur Google mais rien n'est sorti. J'ai une classe TestCase qui hérite de WebTestCase, avec quelques méthodes que je veux utiliser dans toutes mes unités/tests fonctionnels:Symfony 2 + Doctrine 2 + PHPUnit 3.5: Sérialisation de l'exception de fermeture

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

Ensuite, mon test unitaire:

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

Il travaillait avant , mais, tout à coup, après que je mis à jour mes vendeurs (doctrine inclus), il a commencé à jeter cette exception:

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 

J'ai trouvé que le problème vient du chargement du luminaire. Si je supprime le code qui charge les appareils, cela fonctionne.

Est-ce que quelqu'un sait ce qui pourrait être mauvais dans mon code? Est-ce la meilleure façon de charger les appareils?

Merci!

Répondre

86

Pas techniquement lié à votre problème. Cependant, j'ai eu beaucoup de mal à résoudre le problème de "Serialization of 'Closure' n'est pas autorisé" lors de l'utilisation de PHPUnit, et cette question est le meilleur résultat de Google. Le problème vient du fait que PHPUnit sérialise tous les $ GLOBALS dans le système pour les sauvegarder pendant que le test est en cours. Il les restaure ensuite une fois le test terminé. Cependant, si vous avez des fermetures dans votre espace GLOBAL, cela va causer des problèmes. Il y a deux façons de le résoudre.

Vous pouvez désactiver totalement la procédure de sauvegarde globale à l'aide d'une annotation.

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

Ou, si vous savez quelle variable est l'origine du problème (chercher un lambda var_dump ($ GLOBALS)), vous pouvez simplement la liste noire de la variable de problème (s).

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

Merci pour votre réponse! C'est effectivement ce que je devais faire pour résoudre la plupart de mes problèmes avec cette exception. Le seul problème que j'ai vient apparemment du composant Validator de Symfony 2 dans mes tests. Malheureusement, je ne pouvais pas comprendre pourquoi cela arrive encore. – Adrian

+0

Cela aurait été une telle douleur à travailler par moi-même. +1 pour la réponse utile – Rowan

+1

Cela semble avoir été corrigé dans PHPUnit 3.6: https://github.com/sebastianbergmann/phpunit/pull/352 – scribu

4

Vous pouvez également essayer.

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