Recentemente, eu fui TDDing um método de fábrica. O método era criar um objeto simples ou um objeto embrulhado em um decorador. O objeto decorado pode ser de um dos vários tipos, todos estendendo a StrategyClass.
No meu teste, eu queria verificar se a classe do objeto retornado é como o esperado. Isso é fácil quando o objeto comum é retornado, mas o que fazer quando ele é embrulhado em um decorador?
Eu codifico em PHP para que eu pudesse usar ext/Reflection
para descobrir uma classe de objeto empacotado, mas parecia-me complicar demais as coisas e, de certa forma, repetir as regras do TDD.
Em vez I decidiu introduzir getClassName()
que voltaria nome da classe do objeto quando chamado de StrategyClass. Quando chamado do decorador, no entanto, retornaria o valor retornado pelo mesmo método no objeto decorado.
Algum código para deixar mais claro:
interface StrategyInterface {
public function getClassName();
}
abstract class StrategyClass implements StrategyInterface {
public function getClassName() {
return \get_class($this);
}
}
abstract class StrategyDecorator implements StrategyInterface {
private $decorated;
public function __construct(StrategyClass $decorated) {
$this->decorated = $decorated;
}
public function getClassName() {
return $this->decorated->getClassName();
}
}
E um teste PHPUnit
/**
* @dataProvider providerForTestGetStrategy
* @param array $arguments
* @param string $expected
*/
public function testGetStrategy($arguments, $expected) {
$this->assertEquals(
__NAMESPACE__.'\\'.$expected,
$this->object->getStrategy($arguments)->getClassName()
)
}
//below there's another test to check if proper decorator is being used
Meu argumento aqui é: está correto introduzir métodos que não têm outro uso senão facilitar os testes de unidade? De alguma forma, não parece certo para mim.