Diciamo che ho una classe:TDD - Dipendenze che non può essere preso in giro
class XMLSerializer {
public function serialize($object) {
$document = new DomDocument();
$root = $document->createElement('object');
$document->appendChild($root);
foreach ($object as $key => $value) {
$root->appendChild($document->createElement($key, $value);
}
return $document->saveXML();
}
public function unserialze($xml) {
$document = new DomDocument();
$document->loadXML($xml);
$root = $document->getElementsByTagName('root')->item(0);
$object = new stdclass;
for ($i = 0; $i < $root->childNodes->length; $i++) {
$element = $root->childNodes->item($i);
$tagName = $element->tagName;
$object->$tagName = $element->nodeValue();
}
return $object;
}
}
Come faccio a testare questo in isolamento? Durante il test di questa classe, sto anche testando la classe DomDocument
ho potuto passare l'oggetto del documento:
class XMLSerializer {
private $document;
public function __construct(\DomDocument $document) {
$this->document = $document;
}
public function serialize($object) {
$root = $this->document->createElement('object');
$this->document->appendChild($root);
foreach ($object as $key => $value) {
$root->appendChild($this->document->createElement($key, $value);
}
return $this->document->saveXML();
}
public function unserialze($xml) {
$this->document->loadXML($xml);
$root = $this->document->getElementsByTagName('root')->item(0);
$object = new stdclass;
for ($i = 0; $i < $root->childNodes->length; $i++) {
$element = $root->childNodes->item($i);
$tagName = $element->tagName;
$object->$tagName = $element->nodeValue();
}
return $object;
}
}
che sembra risolvere il problema, però, ora il mio test non è in realtà facendo nulla. Ho bisogno di fare una finta DomDocument restituire il XML sto testando nel test:
$object = new stdclass;
$object->foo = 'bar';
$mockDocument = $this->getMock('document')
->expects($this->once())
->method('saveXML')
->will(returnValue('<?xml verison="1.0"?><root><foo>bar</foo></root>'));
$serializer = new XMLSerializer($mockDocument);
$serializer->serialize($object);
che ha diversi problemi:
- io non sono in realtà una prova del metodo a tutti, tutto quello che ho' m controllo è che il metodo restituisce il risultato di
$document->saveXML()
- la prova è consapevole della implementazione del metodo (che utilizza DOMDocument per generare il codice XML)
- il test avrà esito negativo se la classe viene riscritto per utilizzare SimpleXML o di un altro libreria xml, anche se è così potrebbe produrre il risultato corretto
così posso testare questo codice in isolamento? Sembra che io non possa ... esiste un nome per questo tipo di dipendenza che non può essere deriso perché il suo comportamento è essenzialmente richiesto per il metodo che viene testato?
Perché è necessario testarlo isolatamente? – kenjis
Perché in un caso di utilizzo del mondo reale in cui la dipendenza non è incorporata (o DomDocument) se il test fallisce, non saprò se il problema riguarda l'implementazione del metodo che sto testando, o uno degli oggetti che costruisce . Naturalmente posso fare test separati per quelli, ma è inefficiente eseguire tutti i test ogni volta durante lo sviluppo. Come dice qui: https://msdn.microsoft.com/en-us/library/hh549175.aspx "Isolando il tuo codice per il test, sai che se il test fallisce, la causa è lì e non da qualche altra parte", rende lo sviluppo/debugging più veloce se i test sono isolati. –