remarks cref c# tdd dependency-injection mocking dependencies

cref - remarks c#



Usar objetos falsos fuera de las pruebas, ¿mala práctica? (3)

Estoy trabajando en un proyecto donde hay una gran cantidad de mensajes de servicio externo. Una buena forma de describirlo de una manera ligeramente "hipérbolas" sería una aplicación donde el sistema debe enviar mensajes a la API de Flicker, a la API de Facebook y a la API de Netflix.

Para admitir escenarios desconectados, problemas de registro, usabilidad del desarrollador, configuración, etc. He experimentado usando un enfoque que usa mucho genéricos y árboles de expresión. El resultado final se ve así:

Messenger<NetflixApi>.SendCustom( netflix => netflix.RecommendMovie("my message"));

En general, estoy contento con el resultado final, pero siento que cometí un error o que pasé por alto un director de diseño en algún lugar con respecto a las pruebas y los escenarios desconectados.

Durante las pruebas, ya sean automáticas, de unidades o basadas en humanos, implementé una fábrica de objetos que inicialmente usa DI para realizar la acción correcta en "Modo directo" y usé Mocks para proporcionar una especie de mensajero estéril que no hace nada en todo cuando está en modo de prueba.

Solo he visto o leído que Mocks se usa en modo TDD puro y no se usa para ser un objeto tonto. Los enfoques que he visto girarían en torno al borrado o burlarse de la funcionalidad de comunicación HTTP de la que dependen todas las API que estoy usando.

Mi principal preocupación es que todos los diferentes servicios a los que espero conectar terminaré teniendo que hacer un montón de trabajo granular sustituyendo la implementación de HTTP específica y si utilizo un método de código auxiliar tendré 3 clases para cada uno de estos servicios. (IService, ConcreteService, StubService) y mantenerlos al implementar un nuevo método o cambiar cualquier cosa sería un verdadero PITA.

En la implementación actual, estoy usando Mocks para obtener el "modo estéril" de forma gratuita casi sin tener que implementar nada adicional solo para cumplir con un cierto principio de prueba.

La pregunta es ¿me estoy perdiendo algo? ¿Violé a un director de diseño usando Mocks de una manera más ... conveniente?

¿Alguien puede ofrecer algún consejo sobre cómo obtener un modo estéril de muchos servicios externos diferentes sin saltar a través de muchos aros?

¿Esta pregunta tiene sentido?

Gracias por todas las respuestas.

Editar # 1:

No estaba claro en mi pregunta original. Cualquier objeto nulo o simulado debe ser utilizado puramente en un entorno de desarrollo / depuración / prueba. En producción, el código que envía estos mensajes será la implementación real de ellos.

Voté a todo el mundo porque parece que hay muchas soluciones diferentes para este problema y exploraré cada una de ellas.

Por favor, no crea que esta pregunta ha sido respondida todavía, agradecería tantos consejos como pueda obtener.


Me parece que es posible que desee echarle un vistazo al patrón de proxy. Desea algo que actúe como varios servicios incluso cuando está desconectado de los servicios reales. Por lo tanto, sería mejor que tu código hablara con un proxy en lugar de con el real. Luego, el proxy puede hacer lo que necesite dependiendo del estado actual de la conexión.


Creo que es posible que necesites aclarar tu pregunta. No estoy seguro de si está hablando de utilizar pruebas dobles en las pruebas sin tropezar o probar las expectativas (usándolas como falsificaciones para cumplir con las interfaces requeridas) o si está hablando sobre el uso de simulacros en un escenario de producción para completar los servicios que no están disponibles (su escenario desconectado).

Si está hablando en situaciones de prueba: los simulacros son dobles de prueba. No hay nada de malo en probar el uso de falsificaciones en lugar de simulaciones o talones. Si no necesita usar el servicio en una prueba específica y está allí para proporcionar una interfaz determinada que el objeto bajo prueba tiene una dependencia entonces está bien. Eso no está rompiendo ningún principio de prueba.

Las buenas bibliotecas burlonas están difuminando las líneas entre simulacros, trozos y falsificaciones.

Eche un vistazo a parte de la información de Martin Fowler sobre los diferentes tipos de dobles de prueba. Las burlas no son talones , pruebas de prueba .

Me gusta mucho la forma en que moq permite un continuo entre objetos ficticios, falsos, stub y simulados sin necesidad de saltar a través de aros para obtener comportamientos específicos. Compruébalo .

Si está hablando de usar burlas en su escenario desconectado para el uso de producción ... estaría preocupado. Un falso devolverá objetos nulos o valores predeterminados para cualquier llamada que realice. Esto perderá complejidad en todo el código que consuma estos servicios (deberán controlar la comprobación de valores de retorno nulos y matrices vacías ...). Creo que tendría más sentido codificar su escenario desconectado / estéril para manejar que las dependencias mismas no están disponibles en lugar de aceptar implementaciones simuladas de ellas y continuar como si todo estuviera funcionando.


Hay un patrón de diseño llamado Objeto nulo. Un objeto nulo es un objeto que implementa una interfaz, por lo que podría usarse en un escenario como el suyo.

Lo importante sobre el objeto nulo es que NO devuelva nulo en lugares donde eso podría romper el sistema.

El objetivo del objeto nulo es tener una implementación vacía y simple de algo, como un simulacro, pero para ser utilizado en el entorno de producción.

El ejemplo más simple es algo como esto:

class Logger{ private static ILogger _Logger; static Logger(){ //DI injection here _Logger = new NullLogger(); //or _Logger = new TraceLogger(); } } interface ILogger{ void Log(string Message); } internal class TraceLogger:ILooger{ public void Log(string Message){ //Code here } } internal class NullLogger{ public void Log(string Message){ //Don''t don anything, in purporse } }

Espero que esto te pueda ayudar