2012-02-22 11 views
28

Cuando estoy probando unitario mi código php con PHPUnit, estoy tratando de encontrar la manera correcta de burlar un objeto sin burlar ninguno de sus métodos.Creando un simulacro en phpunit sin burlar ningún método?

El problema es que si no llamo al getMockBuilder()->setMethods(), se burlarán todos los métodos del objeto y no puedo llamar al método que quiero probar; pero si yo haga llame al setMethods(), entonces tengo que decirle qué método usar para simular pero no quiero simular ningún método. Pero necesito crear el simulacro para poder evitar llamar al constructor en mi prueba.

Aquí está un ejemplo trivial de un método que me gustaría probar:

class Foobar 
{ 
    public function __construct() 
    { 
     // stuff happens here ... 
    } 

    public function myMethod($s) 
    { 
     // I want to test this 
     return (strlen($s) > 3); 
    } 
} 

podría probar myMethod() con:

$obj = new Foobar(); 
$this->assertTrue($obj->myMethod('abcd')); 

Pero esto sería llamar al constructor de Foobar, que no lo hago querer. Así que en lugar que iba a tratar:

$obj = $this->getMockBuilder('Foobar')->disableOriginalConstructor()->getMock(); 
$this->assertTrue($obj->myMethod('abcd')); 

Pero llamar sin usar getMockBuilder()setMethods() resultará en todos sus métodos que se burlen y volviendo nula, por lo que mi llamada a myMethod() devolverá un valor nulo y sin tocar el código tengo la intención de probar.

Mi solución hasta ahora ha sido la siguiente:

$obj = $this->getMockBuilder('Foobar')->setMethods(array('none')) 
    ->disableOriginalConstructor()->getMock(); 
$this->assertTrue($obj->myMethod('abcd')); 

Esto burlarse de un método denominado 'ninguno', que no existe, pero PHPUnit no le importa. Dejará myMethod() sin bloquear para que yo pueda llamarlo, y también me permitirá deshabilitar el constructor para que no lo llame. ¡Perfecto! Excepto que parece una trampa tener que especificar un nombre de método que no existe: 'ninguno', 'blargh' o 'xyzzy'.

¿Cuál sería la forma correcta de hacerlo?

Respuesta

38

Puede pasar null a setMethods() para evitar burlarse de cualquier método. Pasar una matriz vacía simulará todos los métodos. Este último es el valor predeterminado para los métodos que ha encontrado.

Dicho esto, diría que la necesidad de hacer esto podría señalar un defecto en el diseño de esta clase. ¿Debería este método estar estático o moverse a otra clase? Si el método no requiere una instancia completamente construida, es una señal para mí que podría ser un método de utilidad que podría estartico.

+3

Muchas gracias! Parece que setMethods (null) es lo que quiero; esto no hace que se burlen de los métodos. setMethods (array()), por otro lado, parece causar todos los métodos para ser burlados, lo mismo que no usar setMethods() en absoluto. No pude encontrar esto documentado en ningún lado. Sin embargo, ¿a qué te refieres con "padres vacíos"? –

+0

Además, estoy perplejo por tu comentario. Además de los detalles específicos del ejemplo trivial de myMethod() que proporcioné arriba, ¿por qué un método que necesita ser probado de esta manera te hace sentir que el método debería moverse a otra clase o estar estático? –

+0

@BrianKendig - Autocorrect falla en "padres" que deberían ser "parens". :) Acabo de verificar la fuente y no hay ningún valor predeterminado, así que debes pasar 'null'. –

3

Otra solución hacky, pero sucinta es simplemente para enumerar el constructor de la magia como uno de los métodos puede ser burlado:

$mock = $this->getMock('MyClass', array('__construct')); 
-8

Esto funcionó para mí:

$this->getMock($class, array(), array(), '', false); 
+0

El punto se omite por completo – dVaffection

0

O simplemente puede usar getMock() directamente .

$mock = $this->getMock('MyClass', null, array(), null, false);

+0

getMock() está en desuso – krazyweb

+0

Sí. Voté por la respuesta aceptada. – Ryan

Cuestiones relacionadas