query preparadas example ejemplos consultas php unit-testing pdo phpunit

preparadas - php pdo execute



Burlarse del objeto PDO usando PHPUnit (3)

Tengo dificultades para burlarme del objeto PDO con PHPUnit.

No parece haber mucha información en la web acerca de mi problema, pero de lo que puedo deducir:

  1. PDO tiene los métodos "finales" __wakeup y __sleep que evitan que se serialicen.
  2. La implementación del objeto simulado de PHPunit serializa el objeto en algún punto.
  3. Las pruebas unitarias fallan con un error PHP generado por PDO cuando esto ocurre.

Hay una función para evitar este comportamiento, agregando la siguiente línea a su prueba de unidad:

class MyTest extends PHPUnit_Framework_TestCase { protected $backupGlobals = FALSE; // ... }

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

Esto no funciona para mí, mi prueba todavía produce un error.

Código de prueba completo:

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

¿Algún pro de PHPUnit me ayuda?

Gracias,

Ben


$ backupGlobals no lo ayuda, porque este error proviene de otro lado. PHPUnit 3.5.2 (posiblemente versiones anteriores también) tiene el siguiente código en 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''] ) ); }

Este "truco" con unserialize se usa cuando le pides a getMock que no ejecute el constructor original y este falla rápidamente con PDO.

Entonces, ¿cómo funciona alrededor?

Una opción es crear un ayudante de prueba como este

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

El objetivo aquí es deshacerse del constructor original de PDO, que no necesita. Luego, cambie su código de prueba a esto:

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

Crear un simulacro como este ejecutará el constructor original, pero como ahora es inofensivo gracias a la prueba de simulacro de ayuda de prueba de PDDO, puede continuar con las pruebas.


¿Estás instanciando tu caso de prueba en tu caso de prueba?

$classToTest = new MyTest($pdoMock);

En este momento, esencialmente estás probando tu caso de prueba. Debería ser algo así como:

$classToTest = new My($pdoMock);


Lo mejor que puedo pensar es usar runkit y redefinir los dos métodos finales como protegidos usando runkit_function_redefine.

No para obtener habilitar la configuración runkit.internal_override en php.ini.

Y como siempre, como con eval, si runkit parece ser la respuesta, la pregunta probablemente sea incorrecta :)