2010-11-20 15 views
7

Me pregunto si hay una forma bastante concisa de burlar objetos que admiten el encadenamiento de métodos ... así, por ejemplo, un objeto de consulta de base de datos puede tener una llamada a este método:Simulacros de objetos que admiten métodos de encadenamiento

$result = $database->select('my_table')->where(array('my_field'=>'a_value'))->limit(1)->execute(); 

El problema surge si tengo que simular dos consultas de selección diferentes para que arrojen resultados diferentes. ¿Algunas ideas?

Esto es específicamente sobre PHPUnit, pero las experiencias de otros marcos de pruebas de unidades ayudarán.

+0

Puede por favor aclarar si desea burlarse del objeto, por ejemplo, averiguar si se invoca o resguardar el valor de retorno de una llamada a un método. O en otras palabras, explique para qué está intentando usar el doble de prueba. – Gordon

+0

@Gordon Lo siento, tiendo a usar los términos simulacro y resguardo indistintamente. Mal hábito. En todo mi conjunto de pruebas, me gustaría hacer las dos cosas. Por lo tanto, en este ejemplo, podría resguardar el valor de retorno de una consulta de selección, pero simular una inserción. Si tiene sugerencias para uno u otro, eso ayudaría. Gracias. –

+0

lo siento, todavía no entiendo completamente lo que estás tratando de hacer. ¿Podrías mostrar el caso de prueba por favor? – Gordon

Respuesta

14

no estoy seguro de que esto es lo que está buscando, así que por favor deje un comentario:

class StubTest extends PHPUnit_Framework_TestCase 
{ 
    public function testChainingStub() 
    { 
     // Creating the stub with the methods to be called 
     $stub = $this->getMock('Zend_Db_Select', array(
      'select', 'where', 'limit', 'execute' 
     ), array(), '', FALSE); 

     // telling the stub to return a certain result on execute 
     $stub->expects($this->any()) 
      ->method('execute') 
      ->will($this->returnValue('expected result')); 

     // telling the stub to return itself on any other calls 
     $stub->expects($this->any()) 
      ->method($this->anything()) 
      ->will($this->returnValue($stub)); 

     // testing that we can chain the stub 
     $this->assertSame(
      'expected result', 
      $stub->select('my_table') 
       ->where(array('my_field'=>'a_value')) 
       ->limit(1) 
       ->execute() 
     ); 
    } 
} 

Esto se puede combinar con las expectativas:

class StubTest extends PHPUnit_Framework_TestCase 
{ 
    public function testChainingStub() 
    { 
     // Creating the stub with the methods to be called 
     $stub = $this->getMock('Zend_Db_Select', array(
      'select', 'where', 'limit', 'execute' 
     ), array(), '', FALSE); 

     // overwriting stub to return something when execute is called 
     $stub->expects($this->exactly(1)) 
      ->method('execute') 
      ->will($this->returnValue('expected result')); 

     $stub->expects($this->exactly(1)) 
      ->method('limit') 
      ->with($this->equalTo(1)) 
      ->will($this->returnValue($stub)); 

     $stub->expects($this->exactly(1)) 
      ->method('where') 
      ->with($this->equalTo(array('my_field'=>'a_value'))) 
      ->will($this->returnValue($stub)); 

     $stub->expects($this->exactly(1)) 
      ->method('select') 
      ->with($this->equalTo('my_table')) 
      ->will($this->returnValue($stub)); 

     // testing that we can chain the stub 
     $this->assertSame(
      'expected result', 
      $stub->select('my_table') 
       ->where(array('my_field'=>'a_value')) 
       ->limit(1) 
       ->execute() 
     ); 
    } 
} 
+0

Parece que voy a tener que usar este método, con una devolución de llamada que varía el resultado ... ya sea basado en un contador o basado en la traza inversa, dependiendo de cuál sea el más apropiado. No es tan conciso como esperaba, pero funcionará. Gracias a todos por las contribuciones. –

+0

@Nathan eso es lo que no entiendo :) ¿Qué estás tratando de hacer que necesites mirar hacia atrás? Simplemente haz que 'execute' devuelva lo que esperas que devuelva toda la cadena. – Gordon

+0

Pero, ¿qué sucede si realizo dos consultas diferentes en un caso de prueba? Ahí es donde se pone difícil. –

0

Esto podría no ser la respuesta que está buscando, pero me escribió un marco de objeto de burla de un par de años atrás, que se encargará de este tipo de "depende de la entrada" afirmación bien:

http://code.google.com/p/yaymock/

http://code.google.com/p/yaymock/wiki/Expectations

lo he escrito para su uso en las pruebas de unidad que respaldan Swift Mailer, pero no ha sido ampliamente adoptado por cualquier otro proyecto (que yo sepa). El objetivo era proporcionar un mejor control e introspección de las invocaciones de objeto simuladas que las proporcionadas por PHPUnit y SimpleTest.

+0

Gracias. Lo echaré un vistazo, pero no estoy seguro de estar dispuesto a usar otro framework simulado (solo para llegar al final de la migración de mis pruebas existentes desde SimpleTest). –

+0

Sí, para ser sincero, probablemente también me quedaré con algo más utilizado, especialmente si es probable que otros desarrolladores trabajen con el mismo código y no quieren que tengan que pasar un día averiguando "otro "simulacro de marco de trabajo;) Ciertamente no estoy apegado a él, pero hace un buen trabajo en lo que estaba escrito, así que pensé en mencionarlo de todos modos. – d11wtq

1

Sé que es una vieja cuestión, pero podría ayudar más a los futuros jugadores de Google.

También estaba teniendo problemas para encontrar un marco que proporcione una sintaxis simple y fácil para burlar & encadenamiento del método de troceo. luego decidí escribir una biblioteca burlona simple y fácil de usar.

ejemplo

Uso:

// Creating a new mock for SimpleClassForMocking 
$mock = ShortifyPunit::mock('SimpleClassForMocking'); 

    ShortifyPunit::when($mock)->first_method() 
          ->second_method(2,3)->returns(1); 

    ShortifyPunit::when($mock)->first_method() 
          ->second_method(2,3,4)->returns(2); 

    ShortifyPunit::when($mock)->first_method(1) 
          ->second_method(2,3,4)->returns(3); 

    ShortifyPunit::when($mock)->first_method(1,2,3) 
          ->second_method(1,2)->third_method()->returns(4); 

    $mock->first_method()->second_method(2,3); // returns 1 
    $mock->first_method()->second_method(2,3,4); // returns 2 
    $mock->first_method(1)->second_method(2,3,4); // returns 3 
    $mock->first_method(1,2,3)->second_method(1,2)->third_method(); // return 4 

GitHub:

https://github.com/danrevah/ShortifyPunit#stubbing-method-chanining

Cuestiones relacionadas