Pregunta

Estoy tratando de probar una clase que gestiona el acceso a datos en la base de datos (ya sabes, CRUD, esencialmente). La biblioteca de base de datos que estamos utilizando tiene una API en la que primero obtiene el objeto de tabla mediante una llamada estática:

function getFoo($id) {
  $MyTableRepresentation = DB_DataObject::factory("mytable");
  $MyTableRepresentation->get($id);
  ... do some stuff
  return $somedata
}

... tienes la idea.

Estamos tratando de probar este método, pero burlándonos de las cosas de DataObject para que (a) no necesitemos una conexión db real para la prueba, y (b) ni siquiera necesitemos incluir la biblioteca DB_DataObject para la prueba.

Sin embargo, en PHPUnit parece que no puedo obtener $ this- > getMock () para configurar adecuadamente una llamada estática. Tengo ...

        $DB_DataObject = $this->getMock('DB_DataObject', array('factory'));

... pero la prueba todavía dice método desconocido "fábrica". Sé que está creando el objeto, porque antes decía que no podía encontrar DB_DataObject. Ahora si puede. Pero, ¿ningún método?

Lo que realmente quiero hacer es tener dos objetos simulados, uno para el objeto de tabla devuelto también. Entonces, no solo necesito especificar que factory es una llamada estática, sino que también devuelve algún otro objeto simulado especificado que ya configuré.

Debo mencionar como advertencia que hice esto en SimpleTest hace un tiempo (no puedo encontrar el código) y funcionó bien.

¿Qué da?

[ACTUALIZACIÓN]

Estoy empezando a comprender que tiene algo que ver con la expectativa ()

¿Fue útil?

Solución

Estoy de acuerdo con los dos en que sería mejor no usar una llamada estática. Sin embargo, supongo que olvidé mencionar que DB_DataObject es una biblioteca de terceros, y la llamada estática es su mejor práctica para el uso de su código, no la nuestra. Hay otras formas de usar sus objetos que implican construir el objeto devuelto directamente. Simplemente deja esas malditas declaraciones include / require en cualquier archivo de clase que esté usando esa clase DB_DO. Eso apesta porque las pruebas se romperán (o simplemente no se aislarán) si, mientras tanto, intentas burlarte de una clase del mismo nombre en tu prueba, al menos eso creo.

Otros consejos

Cuando no pueda alterar la biblioteca, modifique su acceso a ella. Refactorice todas las llamadas a DB_DataObject :: factory () a un método de instancia en su código:

function getFoo($id) {
  $MyTableRepresentation = $this->getTable("mytable");
  $MyTableRepresentation->get($id);
  ... do some stuff
  return $somedata
}

function getTable($table) {
  return DB_DataObject::factory($table);
}

Ahora puede usar una simulación parcial de la clase que está probando y hacer que getTable () devuelva un objeto de tabla simulada.

function testMyTable() {
  $dao = $this->getMock('MyTableDao', array('getMock'));
  $table = $this->getMock('DB_DataObject', ...);
  $dao->expects($this->any())
      ->method('getTable')
      ->with('mytable')
      ->will($this->returnValue($table));
  $table->expects...
  ...test...
}

Este es un buen ejemplo de dependencia en su código: el diseño ha imposibilitado la inyección en un simulacro en lugar de la clase real.

Mi primera sugerencia sería intentar refactorizar el código para usar una instancia en lugar de una llamada estática.

Lo que falta (¿o no?) de su clase DB_DataObject es un configurador para pasar un objeto db preparado antes de llamar al método de fábrica. De esa manera, puede pasar un simulacro o un objeto db personalizado (con la misma interfaz) en caso de necesidad.

En su configuración de prueba:

 public function setUp() {
      $mockDb = new MockDb();
      DB_DataObject::setAdapter($mockDb);
 }

El método factory () debería devolver la instancia de base de datos simulada. Si aún no está integrado en su clase, probablemente también tendrá que refactorizar el método factory () para que funcione.

¿Necesita / incluye el archivo de clase para DB_DataObject en su caso de prueba? Si la clase no existe antes de que PHPUnit intente burlarse del objeto, puede obtener errores como este.

Con la extensión PHPUnit MockFunction más runkit también puedes burlarte de los métodos estáticos. Tenga cuidado, porque es un parche de mono y, por lo tanto, solo debe usarse en casos extremos. No sustituye las buenas prácticas de programación.

https://github.com/tcz/phpunit-mockfunction

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top