¿Es esencial la inyección de dependencia para la prueba de la unidad?

47

¿Es esencial usar inyección de dependencia (DI) para realizar pruebas unitarias?

No puedo pensar en otra alternativa para aislar el código para que pueda probarse. Además, todos los ejemplos que he visto utilizan este patrón. ¿Se debe a que es la única opción viable o existen otras alternativas?

    
pregunta Tom Squires 22.03.2012 - 16:34

7 respuestas

35

DI hace que las pruebas unitarias sean mucho más fáciles. Pero todavía puedes escribir pruebas unitarias sin DI. Ya se han escrito muchas pruebas unitarias antes de que se generalice la DI. (Por supuesto, algunas de estas técnicas utilizadas son idénticas o muy similares a las de DI sin saber que tienen un nombre elegante :-)

Yo mismo he utilizado, por ejemplo. Interfaces y fábricas mucho antes de aprender sobre DI. El nombre real de la clase de fábrica puede haber sido leído desde un archivo de configuración o pasado al SUT como un argumento.

Otro enfoque es el uso de singletons (o datos de acceso global en general). Sí, ya sé que no es recomendado por muchos (incluido yo mismo) en general. Sin embargo, puede ser viable en situaciones específicas, especialmente si el singleton contiene datos de configuración estáticos que no son específicos para cada caso de prueba, pero difieren entre la producción y el entorno de prueba. Por supuesto, tiene sus problemas conocidos, por lo que DI es superior si puedes usarlo. Pero a menudo (por ejemplo, en sistemas heredados) no puedes.

Hablando de eso, Trabajando de manera efectiva con el código heredado describe muchos trucos para obtener el código heredado cubierto por las pruebas . Muchos de estos no son agradables, y no son una solución a largo plazo. Pero le permiten crear las primeras pruebas de unidades valiosas para un sistema que de otra manera no se puede probar ... lo que le permite comenzar a refactorizar y, eventualmente (entre otras), introducir DI.

    
respondido por el Péter Török 22.03.2012 - 16:37
51

El desacoplamiento es esencial para las pruebas unitarias. DI es una excelente manera de lograr el desacoplamiento.

    
respondido por el nlawalker 22.03.2012 - 17:22
9

Dependiendo de las tecnologías que esté utilizando, puede aislar dependencias sin usar DI. Por ejemplo, en el mundo .NET, Moles le permite aislar dependencias sin el patrón DI.

Dicho esto, creo que estos marcos de aislamiento están escritos y destinados a situaciones en su código con dependencias externas (sistema de archivos, base de datos, etc.). Es decir, el hecho de que uno pueda hacer esto no significa que deba hacerlo.

La inyección de dependencia permite la prueba unitaria, pero también permite la modificación del comportamiento de un objeto sin alterar el código de ese objeto (principio abierto / cerrado). Entonces, no es solo el código comprobable, sino el código flexible que resulta. En general, he descubierto que existe una gran correlación entre el código flexible / mantenible y el código comprobable.

    
respondido por el Erik Dietrich 22.03.2012 - 16:38
4

No, DI no es esencial para las pruebas unitarias, pero ayuda mucho.

Puede utilizar fábricas o localizadores y realizar pruebas como lo haría con DI (simplemente no tan elegante y requeriría más configuración).

Además, Objetos simulados sería importante en sistemas heredados donde muchas llamadas se delegan a funciones en lugar de dependencias. (Los objetos simulados también se pueden utilizar ampliamente en una configuración adecuada)

Puede haber configuraciones donde las pruebas son casi imposibles. Pero esto no se basa en si se usa o no la inyección de dependencia.

    
respondido por el smp7d 22.03.2012 - 17:23
2

No , la inyección de dependencia no es esencial para la prueba de la unidad.

La inyección de dependencia ayuda si tienes una clase que necesita una instancia de clase dependiente para realizar algún subprocesamiento. En lugar de DI, puede separar la lógica de un método de negocio en una parte de obtención de datos (que no es comprobable por unidad) y una parte de cálculo que puede probarse por unidad.

Ejemplo (usando DI) Esta implementación depende de Empleado, Cuenta, ....

 bool hasPermissionToTranferMony(Employee employee, Account from, Account to, Money amount)
 {
     if (amount > 100 && imployee.isStudent())
        return false;
     if (to.getOwner().getFamiliyName() == Employee.getFamiliyName() && ...
        return false; // cannot transfer money to himself;
     ...
 }

Después de separar la recopilación de datos y el cálculo

 bool hasPermissionToTranferMony(Employee employee, Account from, Account to, Money amount)
 {
     return hasPermissionToTranferMony(employee.isStudent(), Employee.getFamiliyName(),  to.getOwner().getFamiliyName(), ....);
 }

 // the actualal permission calculation
 static bool hasPermissionToTranferMony(boolean isStudent, string employeeFamiliyName, string receiverFamiliyName, .....)
     if (amount > 100 && isStudent)
        return false;
     if (receiverFamiliyName == employeeFamiliyName && ...
        return false; // cannot transfer money to himself;
     ...
 }

La parte de cálculo se puede probar fácilmente sin inyección de dependencia.

    
respondido por el k3b 04.05.2012 - 11:23
1
  • La inyección de dependencia no es esencial para las pruebas unitarias

  • Por otra parte, la inversión de control es esencial cuando se desea intercambiar una implementación por otra.

respondido por el CodeART 04.05.2012 - 11:41
0

Sí, hay alternativas al uso de DI para el aislamiento.

Una alternativa es usar fábricas o un ServiceLocator que puede configurarse desde pruebas para devolver objetos simulados en lugar de objetos reales.

Otra es usar un marco de aislamiento adecuado o una herramienta de burla. Tales herramientas existen para casi todos los lenguajes de programación modernos (al menos para Java, C #, Ruby y Python). Pueden aislar una clase que se está probando de la implementación de otras clases / tipos, incluso cuando la clase probada instancia directamente sus dependencias.

    
respondido por el Rogério 31.01.2014 - 21:32

Lea otras preguntas en las etiquetas