Utilizzando PHPUnit e un oggetto fittizio, sto provando a testare del codice che utilizza get_class
per determinare se un oggetto è incluso o meno da un filtro.Test del codice che utilizza get_class con PHPUnit oggetti fittizi
Qui è la classe da testare:
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;
}
}
Ecco il metodo dal mio test di unità:
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));
}
L'oggetto fittizio $containerBlock
si comporta come l'oggetto reale Pwn\ContentBundle\Document\ContainerBlock
; anche il codice che utilizza instanceof
funziona (perché PHPUnit lo rende una sottoclasse della classe reale, credo).
Il codice in prova utilizza get_class
per ottenere un valore di stringa della classe e confrontarlo con una matrice di nomi di classe previsti. Purtroppo, per l'oggetto finto, get_class restituisce qualcosa di simile:
Mock_ContainerBlock_ac231064
(i _ac231064 cambiamenti suffisso su ogni chiamata).
Questo causa il mio test fallire, quindi quali sono le mie opzioni?
- Rilanciare il codice per evitare l'uso di get_class? Questo implica che get_class non dovrebbe essere usato quando si tenta di scrivere codice testabile.
- Utilizzare un'istanza reale della classe ContainerBlock anziché una simulazione? Ciò significa che stiamo testando efficacemente entrambe le classi contemporaneamente.
- Qualche altro trucco incredibilmente intelligente che tutti suggerirai ??? ;)
Grazie per qualsiasi aiuto ...
Buona idea, credo che questo era nella parte posteriore della mia mente in realtà, ma sembra rendere il test in qualche modo "artificiale"; Avrei meno probabilità di individuare un errore con il test stesso. Quindi ora mi chiedo se questo è meglio o peggio che usare oggetti reali invece di mock ... – fazy
@LarsJ Non vedo alcun problema con quello. Il tuo BlockFilter sta testando i nomi delle classi nell'array, quindi passare il nome della classe di Mock è perfettamente a posto. Su un sidenote, mi piacerebbe prendere in giro l'interfaccia al posto del ContainerBlock, dal momento che questo è ciò che chiede il TypeHint su Inclusive. – Gordon
Grazie ancora per tutti i vostri pensieri e commenti; L'ho messo in pratica e funziona bene. – fazy