Symfony 2 + 2 + Doctrine PHPUnit 3.5: serializzazione d'eccezione chiusura
Domanda
Ho cercato di trovare qualcosa su questo su Google, ma niente è venuto fuori. Ho una classe che eredita da TestCase WebTestCase, con alcuni metodi che voglio utilizzare in tutti i test mia unità / funzionali:
<?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 );
}
}
Quindi, la mia unit test:
<?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 );
}
}
Si stava lavorando prima, ma, improvvisamente, dopo aver aggiornato i miei fornitori (dottrina incluso), ha cominciato a lanciare questa eccezione:
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
Ho trovato che il problema deriva dal dispositivo di carico. Se rimuovo il codice che carica infissi, funziona.
Qualcuno sa cosa potrebbe essere sbagliato nel mio codice? È questo il modo migliore di apparecchi di carico?
Grazie!
Soluzione
Non tecnicamente legato al tuo problema. Tuttavia, ho avuto un momento davvero difficile cercare di risolvere il "serializzazione di 'chiusura' non è consentito" problema durante l'utilizzo di PHPUnit, e questa domanda è il risultato superiore di Google.
Il problema deriva dal fatto che PHPUnit serializza tutti i $ GLOBALS nel sistema per indietro necessari mentre il test è in esecuzione. E poi li ripristina dopo il test è fatto.
Tuttavia, se si dispone di eventuali chiusure nel vostro spazio globale, sta andando a causare problemi. Ci sono due modi per risolverlo.
È possibile disattivare la procedura di backup globale totalmente utilizzando un'annotazione.
/**
* @backupGlobals disabled
*/
class MyTest extends PHPUnit_Framework_TestCase
{
// ...
}
In alternativa, se si conosce quale variabile sta causando il problema (aspetto per una lambda a var_dump ($ GLOBALS)), si può solo blacklist la variabile problema (s).
class MyTest extends PHPUnit_Framework_TestCase
{
protected $backupGlobalsBlacklist = array('application');
// ...
}
Altri suggerimenti
Si può anche provare.
<phpunit backupGlobals="false">
<testsuites>
<testsuite name="Test">
<directory>.</directory>
</testsuite>
</testsuites>
</phpunit>