33 votes

Se moquer de l'objet PDO à l'aide de PHPUnit

Je vais avoir de la difficulté à se moquant de l'objet PDO avec PHPUnit.

Il ne semble pas être beaucoup d'informations sur le web à propos de mon problème, mais de ce que j'ai pu rassembler:

  1. PDO a "final" __wakeup et __le sommeil des méthodes qui l'empêche d'être sérialisés.
  2. PHPunit simulée de l'objet de la mise en œuvre serialises l'objet à un certain point.
  3. Les tests unitaires puis échouer avec une erreur PHP généré par PDO lorsque cela se produit.

Il y a une fonctionnalité conçue pour éviter ce problème, ajoutez la ligne suivante à votre unité de test:

class MyTest extends PHPUnit_Framework_TestCase

{    
    protected $backupGlobals = FALSE;
     // ...

}

Source: http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html

Ce n'est pas de travail pour moi, mon test produit toujours une erreur.

Plein de code de test:

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.......

Tout PHPUnit pro me donner un coup de main?

Merci,

Ben

47voto

Anti Veeranna Points 6319

$backupGlobals ne vous aide pas, parce que cette erreur vient d'ailleurs. PHPUnit 3.5.2 (éventuellement 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']
          )
        );
    }

Ce "truc" avec unserialize est utilisé lorsque vous demandez getMock de ne pas exécuter l'original constructeur et il va rapidement échouer avec PDO.

Alors, comment la contourner?

Une option est de créer un test à l'aide comme ceci

class mockPDO extends PDO
{
    public function __construct ()
    {}

}

Le but ici est de se débarrasser de l'original constructeur PDO, que vous n'avez pas besoin. Ensuite, modifiez votre code de test à ceci:

$pdoMock = $this->getMock('mockPDO', array('prepare'));

Création de maquette comme ce sera exécuter d'origine constructeur, mais puisqu'il est désormais inoffensif grâce à mockPDO test helper, vous pouvez poursuivre le test.

2voto

Le mieux que je puisse penser est d'utiliser runkit et de redéfinir les deux méthodes finales comme protégées à l'aide de runkit_function_redefine.

Ne pas obtenir pour activer le paramètre runkit.internal_override dans php.ini.

Et comme toujours, comme avec eval, si runkit semble être la réponse, la question est probablement fausse :)

2voto

netcoder Points 31874

Vous instanciez votre cas de test dans votre cas de test?

 $classToTest = new MyTest($pdoMock);
 

À l'heure actuelle, vous testez essentiellement votre scénario de test. Cela devrait être plus quelque chose comme:

 $classToTest = new My($pdoMock);
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X