Recientemente estuve utilizando un método de fábrica en TDD. El método era crear un objeto simple o un objeto envuelto en un decorador. El objeto decorado podría ser de uno de varios tipos, todos extendiendo StrategyClass.
En mi prueba, quería comprobar si la clase de objeto devuelto es la esperada. Eso es fácil cuando se devuelve el objeto simple, pero ¿qué hacer cuando está envuelto dentro de un decorador?
Codifico en PHP para poder usar ext/Reflection
para encontrar una clase de objeto envuelto, pero me pareció que estaba complicando las cosas, y de alguna manera contra las reglas de TDD.
En lugar de eso, decidí introducir getClassName()
que devolvería el nombre de clase del objeto cuando se llamara desde StrategyClass. Sin embargo, cuando recibe una llamada del decorador, devolverá el valor devuelto por el mismo método en el objeto decorado.
Algún código para que sea más 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();
}
}
Y una prueba de 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
Mi punto aquí es: ¿está bien introducir tales métodos, que no tienen otro uso que hacer que las pruebas unitarias sean más fáciles? De alguna manera no me parece correcto.