2010-11-20 7 views
7

Mi chiedo se ci sia un modo abbastanza conciso di deridere gli oggetti che supportano il concatenamento dei metodi ... quindi, ad esempio, un oggetto query del database potrebbe avere una chiamata al metodo che assomiglia a questo:Oggetti fittizi che supportano i metodi di concatenamento

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

Il problema si presenta se devo prendere in giro due diverse query di selezione in modo che restituiscano risultati diversi. Qualche idea?

Si tratta in particolare di PHPUnit, ma saranno utili le esperienze di altri framework di test delle unità.

+0

Potete per favore chiarire se si vuole prendere in giro l'oggetto, ad esempio, scoprire se è stato invocato o stubato il valore di ritorno di una chiamata di metodo. O in altre parole, per favore spiega cosa stai provando a usare il test double per. – Gordon

+0

@Gordon Spiacente, tendo ad usare i termini mock e stub in modo intercambiabile. Cattiva abitudine. Nella mia intera suite di test, mi piacerebbe fare entrambe le cose. Quindi in questo esempio, potrei stubare il valore di ritorno di una query selezionata, ma prendere in giro un inserto. Se hai suggerimenti per l'uno o l'altro, sarebbe d'aiuto. Grazie. –

+0

scusa, non capisco ancora cosa stai cercando di fare. Potresti mostrare il testcase per favore? – Gordon

risposta

14

io non sono sicuro che questo è quello che stai cercando, quindi si prega di lasciare un commento:

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() 
     ); 
    } 
} 

È possibile combinare questo con le aspettative:

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

Sembra che dovrò usare questo metodo, con un callback di ritorno che varia il risultato ... o in base a un contatore o in base al backtrace, a seconda di quale sia il più appropriato. Non è abbastanza conciso come speravo, ma funzionerà. Grazie a tutti per i contributi. –

+0

@Nathan questa è la cosa che non ottengo :) Cosa stai cercando di fare che hai bisogno di guardare il backtrace? Devi solo eseguire 'execute' return qualunque cosa ti aspetti che l'intera catena restituisca. – Gordon

+0

Ma cosa succede se faccio due query diverse in un caso di test? Ecco dove diventa difficile. –

0

Questo potrebbe non essere la risposta che stai cercando, ma ho scritto un quadro oggetto fittizio di un paio di anni fa che gestirà questa sorta di "dipende l'ingresso" asserzione bene:

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

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

l'ho scritto per l'uso nei test di unità che appoggiano Swift Mailer, ma non è stato ampiamente adottato da altri progetti (che io sappia). Lo scopo era quello di fornire un migliore controllo e introspezione delle invocazioni di oggetti simulati rispetto a quelle fornite da PHPUnit e SimpleTest.

+0

Grazie. Darei un'occhiata a questo, ma non sono sicuro di voler usare ancora un altro finto framework (mi sto avvicinando alla fine della migrazione dei miei test esistenti da SimpleTest). –

+0

Aye, a dire il vero probabilmente starei anche con qualcosa di più usato, specialmente se è probabile che altri sviluppatori lavorino sullo stesso codice e non vogliano che debbano passare un giorno a capire "un altro "mock object framework;) Non sono certamente attaccato ad esso, ma fa un buon lavoro a quello che è stato scritto per farlo quindi ho pensato di parlarne comunque. – d11wtq

1

So che la sua una vecchia questione, ma potrebbe aiutare di più per i futuri googler.

Avevo inoltre problemi nel trovare un framework che fornisse una sintassi semplice e semplice per il deridere il metodo &. poi ho deciso di scrivere una libreria di derisione semplice e facile da usare.

esempio

Usage:

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

Problemi correlati