2012-06-07 23 views
8

Sto scrivendo un test PHPUnit, in cui ho bisogno di deridere qualche dipendenza, ma ho bisogno di un paio di metodi per farlo funzionare come prima. Vale a dire, ho:PHPUnit: mock tutti i metodi tranne alcuni

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

Così stavo facendo qualcosa di simile:

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

e tutto è bene, tranne il metodo thisOneINeed() viene deriso fuori così non ottengo il codice complesso a correre e io bisogno di eseguire per runSomeCode() per funzionare correttamente. Quel codice in thisOneINeed() non chiama altri metodi, ma è necessario per il test corretto e non restituisce un valore fisso, quindi non posso semplicemente inserire static returnValue() lì. E AFAIK PHPunit non ha un metodo come returnValue() che dice "chiama genitore". Ha returnCallback() ma non c'è modo di dirlo "chiama questo metodo per la classe genitore" per quanto ho potuto vedere.

ho potuto fare l'elenco di tutti i metodi in Dependency, rimuoverlo thisOneINeed da esso e passarlo a setMethods() quando si costruisce il finto, ma non mi piace questo approccio, sembra kludgy.

Potrei anche fare questo:

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

e quindi utilizzare MockDependency per costruire l'oggetto fittizio, e questo funziona anche, ma non mi piace dover fare il finto manualmente.

Quindi c'è un modo migliore per farlo?

risposta

9

Penso che se si desidera utilizzare il generatore di mock di PHPUnit, quindi creare una matrice di tutti i metodi, rimuovendo quello necessario e passandolo a setMethods è esattamente quello che devi fare.

Personalmente ho trovato utile in molti casi avere una sottoclasse di ReflectionClass in cui aggiungere metodi quando ne ho bisogno.

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

Si potrebbe anche utilizzare un diverso modello di simulazione che supporta ciò che si vuole fare. Ad esempio, Phake ha un metodo thenCallParent. Ho iniziato a utilizzare Phake di recente perché dovevo essere in grado di acquisire i parametri passati a un metodo. È ben documentato e vale la pena provare.

Problemi correlati