2012-02-22 15 views
28

Kiedy testuję swój kod php za pomocą PHPUnit, próbuję znaleźć właściwy sposób na wyśmiewanie obiektu bez drwi z żadnej z jego metod.Tworzenie makiety w phpunit bez kpienia z jakichkolwiek metod?

Problem polega na tym, że jeśli nie zadzwonię pod numer getMockBuilder()->setMethods(), wszystkie metody na obiekcie będą wyśmiewane i nie będę mógł wywołać metody, którą chcę przetestować; ale jeśli mam do zadzwonić pod numer setMethods(), to muszę powiedzieć, jaką metodę naśmiewać, ale nie chcę drwić żadnych metod w ogóle. Ale muszę stworzyć próbę, aby uniknąć wywoływania konstruktora w moim teście.

Oto trywialny przykład metody chciałbym do badania:

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

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

mogę przetestować myMethod() z:

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

Ale to nazwałbym konstruktora foobar, w których nie chcieć. Zamiast więc będę próbować:

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

Ale nazywając getMockBuilder() bez użycia setMethods() spowoduje wszystkich jego metod jest wyśmiewany i wraca pusty, więc moje wezwanie do myMethod() zwróci NULL bez dotykania kodu zamierzam przetestować.

Moja obejście dotąd to:

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

To będzie kpić metodę o nazwie „none”, która już nie istnieje, ale PHPUnit nie obchodzi. Zostawię on myMethod() niezmieniony, tak żebym mógł go nazwać, a także pozwoli mi wyłączyć konstruktora, tak że go nie nazywam. Idealny! Tyle tylko, że wydaje się, że trzeba oszukiwać, aby podać nazwę metody, która nie istnieje - "none", "blargh" lub "xyzzy".

Jaki byłby właściwy sposób robienia tego?

Odpowiedz

38

Możesz przekazać null do setMethods(), aby uniknąć drwiny z jakichkolwiek metod. Przekazanie pustej tablicy będzie kpić z wszystkich metod. Ta ostatnia jest domyślną wartością dla metod, które znalazłeś.

To powiedziawszy, powiedziałbym, że potrzeba tego może wskazywać na wadę w konstrukcji tej klasy. Czy ta metoda powinna być statyczna lub przeniesiona do innej klasy? Jeśli metoda nie wymaga całkowicie skonstruowanej instancji, jest dla mnie znakiem, że może to być metoda użyteczności, która może być statyczna.

+3

Dziękuję bardzo! Wygląda na to, że setMethods (null) jest tym, czego chcę; to nie powoduje wyśmiewania się z metod. Z drugiej strony setMethods (array()) wydaje się powodować, że wszystkie metody są wyśmiewane, tak samo jak nie używanie w ogóle metody setMethods(). Nie mogłem znaleźć tego udokumentowanego nigdzie. Co masz na myśli przez "pustych rodziców"? –

+0

Ponadto - jestem zaintrygowany twoim komentarzem. Pomijając specyfikę trywialnego przykładu myMethod() podanego powyżej, dlaczego metoda, która musi zostać przetestowana w ten sposób, powoduje, że czujesz, że metoda powinna zostać przeniesiona do innej klasy lub wykonana statycznie? –

+0

@BrianKendig - Autokorekta kończy się niepowodzeniem na "rodzicach", które powinny być "parens". :) Właśnie sprawdziłem źródło i nie ma wartości domyślnej, więc sam musisz przekazać 'null'. –

3

Innym hacky, ale zwięzłe rozwiązanie jest po prostu do listy magiczną konstruktora jako jeden z szydzili metod:

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

ten pracował dla mnie:

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

Punkt jest całkowicie pominięty – dVaffection

0

lub można po prostu użyć getMock() bezpośrednio .

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

+0

getMock() jest przestarzałe – krazyweb

+0

Tak. Głosowałem za zaakceptowaną odpowiedzią. – Ryan

Powiązane problemy