Se moquer de L'objet PDO en utilisant PHPUnit
J'ai du mal à me moquer de L'objet PDO avec PHPUnit.
Il ne semble pas y avoir beaucoup d'informations sur le web sur mon problème, mais à partir de ce que je peux rassembler:
- PDO a 'final' _ _ wakeup et _Méthodes _sleep qui l'empêchent d'être sérialisé.
- l'implémentation d'objet fictif de PHPunit sérialise l'objet à un moment donné.
- les tests unitaires échouent alors avec une erreur PHP générée par PDO lorsque cela se produit.
Il y a une fonctionnalité destinée à empêchez ce comportement, en ajoutant la ligne suivante à votre test unitaire:
class MyTest extends PHPUnit_Framework_TestCase
{
protected $backupGlobals = FALSE;
// ...
}
Source: http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html
Cela ne fonctionne pas pour moi, mon test produit toujours une erreur.
Code de test complet:
class MyTest extends PHPUnit_Framework_TestCase
{
/**
* @var MyTest
*/
private $MyTestr;
protected $backupGlobals = FALSE;
/**
* Prepares the environment before running a test.
*/
protected function setUp()
{
parent::setUp();
}
/**
* Cleans up the environment after running a test.
*/
protected function tearDown()
{
parent::tearDown();
}
public function __construct()
{
$this->backupGlobals = false;
parent::__construct();
}
/**
* Tests MyTest->__construct()
*/
public function test__construct()
{
$pdoMock = $this->getMock('PDO', array('prepare'), array(), '', false);
$classToTest = new MyTest($pdoMock);
// Assert stuff here!
}
// More test code.......
Un PHPUnit pro me donne un coup de main?
Merci,
Ben
3 réponses
$ backupGlobals ne vous aide pas, car cette erreur vient d'ailleurs. PHPUnit 3.5.2 (peut-être aussi des versions antérieures) a le code suivant dans PHPUnit/Framework/Mockobject/Generator.php
if ($callOriginalConstructor &&
!interface_exists($originalClassName, $callAutoload)) {
if (count($arguments) == 0) {
$mockObject = new $mock['mockClassName'];
} else {
$mockClass = new ReflectionClass($mock['mockClassName']);
$mockObject = $mockClass->newInstanceArgs($arguments);
}
} else {
// Use a trick to create a new object of a class
// without invoking its constructor.
$mockObject = unserialize(
sprintf(
'O:%d:"%s":0:{}',
strlen($mock['mockClassName']), $mock['mockClassName']
)
);
}
Cette "astuce" avec unserialize est utilisée lorsque vous demandez à getMock de ne pas exécuter le constructeur d'origine et elle échouera rapidement avec PDO.
Alors, comment le contourner?
Une option consiste à créer un assistant de test comme celui-ci
class mockPDO extends PDO
{
public function __construct ()
{}
}
Le but ici est de se débarrasser du constructeur PDO d'origine, dont vous n'avez pas besoin. Ensuite, changez votre code de test en ceci:
$pdoMock = $this->getMock('mockPDO', array('prepare'));
Créer un mock comme celui-ci exécutera constructeur original, mais comme il est maintenant inoffensif grâce à mockpdo test helper, vous pouvez continuer à tester.
Le mieux que je puisse penser est d'utiliser runkit et de redéfinir les deux méthodes finales protégées en utilisant runkit_function_redefine.
Dont POUR get pour activer le runkit.paramètre internal_override en php.ini.
Et comme toujours, comme avec eval, si runkit semble être la réponse, la question est probablement fausse:)
Vous instanciez votre cas de test dans votre cas de test?
$classToTest = new MyTest($pdoMock);
En ce moment, vous testez essentiellement votre cas de test. Il devrait être plus quelque chose comme:
$classToTest = new My($pdoMock);