Articulo de referencia

Objeto simulado

En programación informática , un objeto simulado es un objeto que imita a un objeto real de forma limitada. Un programador puede usar un objeto simulado como doble de prueba par...

En programación informática , un objeto simulado es un objeto que imita a un objeto real de forma limitada. Un programador puede usar un objeto simulado como doble de prueba para las pruebas de software . Un objeto simulado también se puede usar en programación genérica .

Analogía

Un objeto simulado puede ser útil para el probador de software, al igual que un diseñador de automóviles utiliza un maniquí de prueba de choque para simular a una persona en un impacto vehicular.

Motivación

En una prueba unitaria , los objetos simulados pueden simular el comportamiento de objetos reales complejos y, por lo tanto, resultan útiles cuando un objeto real es poco práctico o imposible de incorporar a una prueba unitaria. Si un objeto presenta alguna de las siguientes características, puede ser útil utilizar un objeto simulado en su lugar:

  • Proporciona resultados no deterministas (por ejemplo, la hora actual o la temperatura actual).
  • Tiene estados que son difíciles de crear o reproducir (por ejemplo, un error de red).
  • Es lento (por ejemplo, una base de datos completa , que tendría que prepararse antes de la prueba).
  • aún no existe o puede cambiar de comportamiento
  • Tendría que incluir información y métodos exclusivamente para fines de prueba (y no para su tarea real).

Por ejemplo, un programa de despertador que hace sonar una campana a una hora determinada podría obtener la hora actual de un servicio de hora. Para probar esto, el programa debe esperar hasta la hora de la alarma para saber si la campana sonó correctamente. Si se utiliza un servicio de hora simulado en lugar del servicio de hora real, se puede programar para que proporcione la hora de la campana (o cualquier otra hora) independientemente de la hora real, de modo que el programa del despertador pueda probarse de forma aislada.

Detalles técnicos

Los objetos simulados tienen la misma interfaz que los objetos reales que imitan, lo que permite que un objeto cliente no sepa si está utilizando un objeto real o uno simulado. Muchos frameworks de objetos simulados permiten al programador especificar qué métodos se invocarán en un objeto simulado, en qué orden, qué parámetros se les pasarán y qué valores devolverá. De este modo, el comportamiento de un objeto complejo, como un socket de red, puede ser imitado por un objeto simulado, lo que permite al programador descubrir si el objeto que se está probando responde adecuadamente a la amplia variedad de estados en los que pueden encontrarse dichos objetos simulados.

Maquetas, falsificaciones o esbozos

Las definiciones de mock, fake y stub no son consistentes en la literatura. [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] No obstante, todos representan un objeto de producción en un entorno de prueba al exponer la misma interfaz.

Independientemente del nombre, la forma más simple devuelve respuestas predefinidas (como en un método auxiliar ) y la forma más compleja imita la lógica completa de un objeto de producción.

Dicho objeto de prueba podría contener aserciones para examinar el contexto de cada llamada. Por ejemplo, un objeto simulado podría verificar el orden en que se llaman sus métodos o la coherencia de los datos entre las llamadas a métodos.

En el libro El arte de las pruebas unitarias [ 7 ], los mocks se describen como objetos ficticios que ayudan a determinar si una prueba falló o pasó al verificar si se produjo una interacción con un objeto. Todo lo demás se define como un stub. En ese libro, los fakes son todo aquello que no es real, que, según su uso, puede ser un stub o un mock .

Establecer expectativas

Consideremos un ejemplo donde se ha simulado un subsistema de autorización. El objeto simulado implementa un método [ 8 ] que coincide con el de la clase de autorización real. Si además expone una propiedad que no está presente en la clase real, se obtienen muchas ventajas. Esto permite que el código de prueba establezca fácilmente la expectativa de que a un usuario se le concederá o no el permiso en la siguiente llamada y, por lo tanto, pueda probar fácilmente el comportamiento del resto del sistema en ambos casos.isUserAllowed(task : Task) : booleanisAllowed : boolean

De forma similar, la configuración de simulación exclusiva podría garantizar que las llamadas posteriores al subsistema provoquen una excepción , un bloqueo sin respuesta o un retorno null, etc. De este modo, es posible desarrollar y probar el comportamiento del cliente ante condiciones de fallo realistas en los subsistemas de back-end , así como sus respuestas esperadas. Sin un sistema de simulación tan sencillo y flexible, probar cada una de estas situaciones podría resultar demasiado laborioso como para considerarlas adecuadamente.

Escritura de cadenas de registro

El método de un objeto de base de datos simulado puede no contener mucho código de implementación (o ninguno). Podría comprobar la existencia y tal vez la validez del objeto Persona que se pasa para guardar (véase la discusión sobre objetos simulados frente a objetos ficticios más arriba), pero más allá de eso, es posible que no haya ninguna otra implementación.save(person : Person)

Esta es una oportunidad perdida. El método simulado podría agregar una entrada a una cadena de registro pública. La entrada no necesita ser más que "Persona guardada", [ 9 ] : 146–7 o puede incluir algunos detalles de la instancia del objeto persona, como un nombre o ID. Si el código de prueba también verifica el contenido final de la cadena de registro después de varias series de operaciones que involucran la base de datos simulada, entonces es posible verificar que en cada caso se ha realizado exactamente la cantidad esperada de guardados de la base de datos. Esto puede encontrar errores invisibles que perjudican el rendimiento, por ejemplo, donde un desarrollador, preocupado por perder datos, ha codificado llamadas repetidas a save()cuando una sola hubiera sido suficiente.

Uso en el desarrollo guiado por pruebas

Los programadores que trabajan con el método de desarrollo guiado por pruebas (TDD) utilizan objetos simulados al escribir software. Los objetos simulados cumplen con los requisitos de interfaz de los objetos reales más complejos y los reemplazan; por lo tanto, permiten a los programadores escribir y probar unitariamente la funcionalidad en un área sin llamar a clases subyacentes o colaboradoras complejas . [ 9 ] : 144–5 El uso de objetos simulados permite a los desarrolladores centrar sus pruebas en el comportamiento del sistema bajo prueba sin preocuparse por sus dependencias. Por ejemplo, probar un algoritmo complejo basado en múltiples objetos que se encuentran en estados particulares se puede expresar claramente utilizando objetos simulados en lugar de objetos reales.

Además de la complejidad y las ventajas de esta separación de responsabilidades , existen problemas prácticos de velocidad. Desarrollar un software realista con TDD puede implicar fácilmente cientos de pruebas unitarias. Si muchas de ellas requieren comunicación con bases de datos, servicios web y otros sistemas externos o en red , el conjunto de pruebas unitarias se volverá rápidamente demasiado lento para ejecutarse con regularidad. Esto, a su vez, genera malos hábitos y reticencia por parte del desarrollador a mantener los principios básicos de TDD.

Cuando los objetos simulados se reemplazan por objetos reales, la funcionalidad de extremo a extremo requerirá pruebas adicionales. Se tratará de pruebas de integración, no de pruebas unitarias.

Limitaciones

El uso de objetos simulados puede acoplar estrechamente las pruebas unitarias a la implementación del código que se está probando. Por ejemplo, muchos frameworks de objetos simulados permiten al desarrollador comprobar el orden y la cantidad de veces que el objeto real que se está probando invocó los métodos del objeto simulado; por lo tanto, una refactorización posterior del código podría provocar que la prueba falle, incluso si todos los métodos del objeto simulado siguen cumpliendo el contrato de la implementación anterior. Esto demuestra que las pruebas unitarias deben probar el comportamiento externo de un método en lugar de su implementación interna. El uso excesivo de objetos simulados como parte de un conjunto de pruebas unitarias puede resultar en un aumento drástico de la cantidad de mantenimiento que se debe realizar en las propias pruebas durante la evolución del sistema a medida que se lleva a cabo la refactorización. Un mantenimiento inadecuado de dichas pruebas durante la evolución podría hacer que se pasen por alto errores que de otro modo serían detectados por pruebas unitarias que utilizan instancias de clases reales. Por el contrario, simplemente simular un método podría requerir mucha menos configuración que configurar una clase real completa y, por lo tanto, reducir las necesidades de mantenimiento.

Los objetos simulados deben modelar con precisión el comportamiento del objeto que simulan, lo cual puede ser difícil de lograr si el objeto simulado proviene de otro desarrollador o proyecto, o si aún no se ha escrito. Si el comportamiento no se modela correctamente, las pruebas unitarias pueden registrar un resultado positivo aunque se produzca un fallo en tiempo de ejecución bajo las mismas condiciones que la prueba unitaria está evaluando, lo que invalida la prueba unitaria. [ 10 ]

Véase también

Referencias

  1. "Mejores prácticas para pruebas unitarias con .NET Core y .NET Standard: hablemos el mismo idioma (Fake, Stubs y Mocks)" . Microsoft Docs . Archivado del original el 3 de septiembre de 2022.
  2. D'Arcy, Hamlet (21 de octubre de 2007). "Los bufones y los esbozos no son espías" . Behind the Times . Archivado del original el 20 de junio de 2017.
  3. "Mocks, Fakes, Stubs and Dummies" . XUnitPatterns.com . Archivado del original el 17 de enero de 2024.
  4. "¿Cuál es la diferencia entre un mock y un stub?" . Stack Overflow . Archivado del original el 4 de julio de 2022.
  5. "¿Cuál es la diferencia entre fingir, burlarse y tropezar?" .
  6. Feathers, Michael (2005). "Detección y separación". Trabajar eficazmente con código heredado . NJ: Prentice Hall. pág. 23 y siguientes. ISBN  0-13-117705-2.
  7. Osherove, Roy (2009). "Pruebas de interacción con objetos simulados, etc.". El arte de las pruebas unitarias . Manning. ISBN 978-1-933988-27-6.
  8. Estos ejemplos utilizan una nomenclatura similar a la empleada en el Lenguaje Unificado de Modelado (UML) .
  9. 1 2 Beck, Kent (2003). Desarrollo guiado por pruebas mediante ejemplos . Boston: Addison Wesley. ISBN 0-321-14653-0.
  10. InJava.com a la burla | O'Reilly Media
  • Tim Mackinnon (8 de septiembre de 2009). "Una breve historia de los objetos simulados" . Mockobjects.com/. Archivado del original el 7 de junio de 2023.
  • Dobles de prueba : una sección de un libro sobre patrones de pruebas unitarias.
  • ¡Todo sobre objetos simulados! Portal sobre objetos simulados
  • "Uso de objetos simulados para pruebas unitarias complejas" . IBM developerWorks. 16 de octubre de 2006. Archivado del original el 4 de mayo de 2007.
  • Pruebas unitarias con objetos simulados en IBM DeveloperWorks
  • Los mocks no son stubs ( Martin Fowler ). Artículo sobre el desarrollo de pruebas con objetos mock. Identifica y compara las escuelas de pruebas "clásica" y "mockista". Aborda aspectos sobre el impacto en el diseño y el mantenimiento.
Obtenido de " https://en.wikipedia.org/w/index.php?title=Mock_object&oldid=1358177907 "