2012-06-07 24 views
8

Estoy escribiendo una prueba PHPUnit, donde necesito burlarme de alguna dependencia, pero necesito un par de métodos para que siga funcionando igual que antes. Es decir, que tiene:PHPUnit: simula todos los métodos, excepto algunos

class Dependency { 
// some stuff not important for the test 
    public function thisOneINeed() { 
    /// complex code 
    } 
// some more stuff 
} 

Así que estaba haciendo algo como esto:

// prepare mock object 
$dep = $this->getMockBuilder('Dependency')->disableOriginalConstructor()->getMock(); 
// mock out some other method that should return fixed value 
$dep->expects($this->any())->method("shouldGetTrue")->will($this->returnValue(true)); 
// run test code, it will use thisOneINeed() and shouldGetTrue() 
$result = $testSubject->runSomeCode($dep); 
$this->assertEquals($expected, $result); 

y todo está bien, excepto thisOneINeed() método puede ser burlado a cabo de manera que no entiendo el código complejo para funcionar y yo necesita que se ejecute para runSomeCode() para que funcione correctamente. Ese código en thisOneINeed() no llama a ningún otro método, pero es necesario para la prueba adecuada y no devuelve un valor fijo, por lo que no puedo simplemente poner returnValue() estático allí. Y AFAIK PHPunit no tiene un método como returnValue() que diga "call parent". Tiene returnCallback() pero no hay forma de decirle "llamar a este método para la clase de padres" hasta donde yo pude ver.

que podría hacer la lista de todos los métodos de Dependency, retire thisOneINeed de ella y pasarlo a setMethods() en la construcción de la maqueta, pero que no me gusta este enfoque, se ve kludgy.

yo también podría hacer esto:

class MockDependency extends Dependency 
{ 
    // do not let the mock kill thisOneINeed function 
    final public function thisOneINeed() 
    { 
     return parent::thisOneINeed(); 
    } 
} 

y luego usar MockDependency para construir el objeto de burla, y esto funciona también, pero no me gusta tener que hacer el simulacro de forma manual.

¿Hay alguna forma mejor de hacerlo?

Respuesta

9

Creo que si se quiere utilizar el constructor de simulacro de PHPUnit, a continuación, crear una matriz de todos los métodos, la eliminación de la que necesita, y pasándolo a setMethods es exactamente lo que necesita hacer.

Personalmente he encontrado útil en muchos casos tener una subclase de ReflectionClass a la que puedo agregar métodos cuando los necesite.

class MyReflectionClass extends ReflectionClass 
{ 
    public function getAllMethodNamesExcept(array $excluded) 
    { 
     $methods = array_diff(
      get_class_methods($this->name), 
      $excluded 
     ); 
     return $methods; 
    } 
} 

También podría utilizar un marco de burla diferente que admita lo que desea hacer. Por ejemplo, Phake tiene un método thenCallParent. Empecé a usar Phake recientemente porque necesitaba poder capturar los parámetros que se pasaron a un método. Está bien documentado y vale la pena intentarlo.

Cuestiones relacionadas