2013-01-04 12 views
5

Używając PHPUnit i obiektu próbnego, próbuję przetestować kod, który używa get_class, aby określić, czy obiekt jest zawarty w filtrze, czy nie.Testowanie kodu, który używa get_class z PHPUnit mock objects

Oto klasy powinien być badany:

class BlockFilter implements FilterInterface 
{ 
    private $classes; 

    public function __construct(array $classes = array()) 
    { 
     $this->classes = $classes; 
    } 

    public function isIncluded(NodeTraversableInterface $node) 
    { 
     if (Type::BLOCK != $node->getDocumentType()) { 
      return false; 
     } 

     if (! empty($this->classes)) { 
      /*** HERE IS THE PROBLEM: ***/ 
      return in_array(get_class($node), $this->classes); 
     } 

     return true; 
    } 
} 

Oto metoda z mojego badanej jednostki:

public function testIfContainerBlockIsIncluded() 
{ 
    $containerBlock = $this->getMock('Pwn\ContentBundle\Document\ContainerBlock'); 
    $containerBlock->expects($this->any())->method('getDocumentType')->will($this->returnValue(Type::BLOCK)); 

    $filter = new BlockFilter(array('Pwn\ContentBundle\Document\ContainerBlock')); 
    $this->assertTrue($filter->isIncluded($containerBlock)); 
} 

makiety obiektów $containerBlock zachowuje się jak prawdziwy obiekt Pwn\ContentBundle\Document\ContainerBlock; nawet kod przy użyciu instanceof działa (ponieważ PHPUnit sprawia, że ​​jest to podklasa prawdziwej klasy, jak sądzę).

Testowany kod używa get_class, aby uzyskać wartość łańcuchową klasy i porównać ją z tablicą oczekiwanych nazw klas. Niestety, dla atrapa obiektu, get_class zwraca coś takiego:

Mock_ContainerBlock_ac231064 

(the _ac231064 przyrostek zmian na każdym wywołaniu).

Powoduje to niepowodzenie mojego testu, więc jakie są moje opcje?

  • Przerób kod, aby uniknąć używania get_class? Oznacza to, że get_class nie powinien być używany podczas próby napisania testowalnego kodu.
  • Użyj prawdziwej instancji klasy ContainerBlock zamiast makiety? Oznacza to, że efektywnie testujemy obie klasy jednocześnie.
  • Jakiś inny niesamowicie sprytny trik, który wszyscy zamierzacie zasugerować ??? ;)

dzięki za pomoc ...

Odpowiedz

2

Pass Imię makiety swojej klasie w badaniu:

new BlockFilter(array(get_class($this->containerBlock))); 
+0

Dobry pomysł, myślę, że to było w mojej głowie, ale to faktycznie wydaje się, że test jest jakoś "sztuczny"; Byłbym mniej skłonny do zauważenia błędu w samym teście. Więc zastanawiam się, czy to jest lepsze, czy gorsze niż używanie prawdziwych obiektów zamiast makiet ... – fazy

+0

@LarsJ Nie widzę żadnego problemu z tym. Twój BlockFilter testuje nazwy klas w tablicy, więc podanie nazwy klasy Mock jest całkowicie w porządku. W tym przewodniku wykpilam interfejs zamiast ContainerBlock, ponieważ o to pyta TypeHint on isIncluded. – Gordon

+1

Jeszcze raz dziękuję za wszystkie twoje myśli i komentarze; Zastosowałem to w praktyce i działa dobrze. – fazy

Powiązane problemy