Realizar pruebas unitarias con dependencias anidadas y clases de fábrica.
Soy nuevo en pruebas unitarias y PHPUnit, pero últimamente estoy leyendo mucho sobre patrones de diseño y pruebas aisladas y he decidido refactorizar una aplicación en la que estoy trabajando para deshacerme de clases estáticas, singletons, dependencias codificadas y cualquier otra cosa definida en el ámbito global, con suerte que sea "comprobable" y no un dolor en el culo para mantener en el futuro, ya que está destinado a ser un proyecto a largo plazo.
Hasta ahora creo que entiendo la teoría detrás de las pruebas de unidad, pero me preguntaba, en un escenario en el que uno de los delegados maneja dependencias de objetos anidadas en una Fábrica, ¿cómo debería uno hacer una prueba de unidad, dijo Fábrica, o simplemente es redundante probarla ? ¿Y cuál es el mejor enfoque para probar que la "cadena" de dependencias funciona bien en sincronización?
Déjame ilustrar las preguntas. Supongamos que tiene el siguiente código "heredado":
<code>class House { protected $material; protected $door; protected $knob; public function __construct() { $this->door = new Door(); $this->knob = $this->door->getKnob(); $this->material = "stone"; echo "House material: ".$this->material . PHP_EOL . "<br/>"; echo "Door material: ".$this->door->getMaterial() . PHP_EOL . "<br/>"; echo "Knob material: ".$this->knob->getMaterial() . PHP_EOL . "<br/>"; } } class Door { protected $material; protected $knob; public function __construct() { $this->knob = new Knob(); $this->material = "wood"; } public function getKnob() { return $this->knob; } public function getMaterial () { return $this->material; } } class Knob { protected $material; public function __construct() { $this->material = "metal"; } public function getMaterial () { return $this->material; } } $house = new House(); </code>
Esto es (según mi entender) malo para las pruebas de unidad, por lo que reemplazamos las dependencias codificadas por DI + una clase de fábrica:
<code>class House { protected $material; protected $door; protected $knob; public function __construct($door) { $this->door = $door; $this->knob = $this->door->getKnob(); $this->material = "stone"; echo "House material: ".$this->material . PHP_EOL . "<br/>"; echo "Door material: ".$this->door->getMaterial() . PHP_EOL . "<br/>"; echo "Knob material: ".$this->knob->getMaterial() . PHP_EOL . "<br/>"; } } class Door { protected $material; protected $knob; public function __construct($knob) { $this->knob = $knob; $this->material = "wood"; } public function getKnob() { return $this->knob; } public function getMaterial () { return $this->material; } } class Knob { protected $material; public function __construct() { $this->material = "metal"; } public function getMaterial () { return $this->material; } } class HouseFactory { public function create() { $knob = new Knob(); $door = new Door($knob); $house = new House($door); return $house; } } $houseFactory = new HouseFactory(); $house = $houseFactory->create(); </code>
Ahora (y nuevamente, por lo que entiendo) House, Door y Knob pueden ser probados en unidad con dependencias burlonas, simplemente bien. Pero:
1) ¿Qué pasa con HouseFactory ahora?
Si uno solo:
No lo pruebe ya que aún no tiene ninguna lógica de aplicación que valga la pena probar y las Fábricas generalmente permanecen así. Supongamos que si las pruebas independientes de Casa, Puerta y Perilla pasan la fábrica deberían estar bien.Refactorice la fábrica de alguna manera, es decir, use funciones dentro de la clase para obtener cada instancia de tal manera que pueda anular estas funciones a través de PHPUnit para devolver objetos simulados, en caso de que haya alguna lógica adicional en la clase que pueda usar algunas pruebas en el futuro.2) ¿Es factible configurar pruebas que dependan de varias dependencias (no simuladas) a la vez? Entiendo que esto no es técnicamente una prueba unitaria (¿pruebas de integración quizás?) Pero supongo que todavía es perfectamente factible usando PHPUnit? Dado el ejemplo anterior, me gustaría poder configurar una prueba que no solo evalúe House, Door, Knob y HouseFactory de forma aislada, sino también los resultados de la interacción de los objetos reales entre sí, tal vez con algunos de sus aspectos. funciones simuladas, como las que tratan con datos. ¿Es PHPUnit una mala elección para este tipo de pruebas?
Gracias de antemano por tu tiempo. Me doy cuenta de que algunas de las suposiciones que estoy haciendo pueden no ser correctas, ya que obviamente no soy un experto en el tema; Las correcciones son bienvenidas y apreciadas.