stringtranslate.com

Objeto simulado

En informática , un objeto simulado es un objeto que imita a un objeto de producción de maneras limitadas. Un programador puede usar un objeto simulado como un 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 evaluador de software, de la misma manera que un diseñador de automóviles utiliza un maniquí de prueba de choque para simular un humano en el impacto de un vehículo.

Motivación

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

Por ejemplo, un programa de despertador que hace sonar una campana a una hora determinada puede obtener la hora actual de un servicio horario. Para probar esto, la prueba debe esperar hasta la hora de la alarma para saber si ha hecho sonar la campana correctamente. Si se utiliza un servicio horario simulado en lugar del servicio horario 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 de despertador se pueda probar 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 un objeto simulado. Muchos marcos de trabajo de objetos simulados disponibles 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 se devolverán. 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 estar dichos objetos simulados.

Simulacros, falsificaciones y esbozos

Las definiciones de mock, fake y stub no son consistentes en la literatura. [1] [2] [3] [4] [5] [6] No obstante, todas 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 preestablecidas (como en un stub de método ) y la forma más compleja imita la lógica completa de un objeto de producción.

Un objeto de prueba de este tipo podría contener afirmaciones para examinar el contexto de cada llamada. Por ejemplo, un objeto simulado podría afirmar el orden en el que se llaman sus métodos o afirmar la coherencia de los datos en las distintas llamadas de métodos.

En el libro The Art of Unit Testing [7], los mocks se describen como objetos falsos que ayudan a decidir si una prueba falló o pasó al verificar si se produjo una interacción con un objeto. Todo lo demás se define como stub. En ese libro, los fakes son cualquier cosa que no sea real, que, según su uso, puede ser stub o mock .

Establecer expectativas

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

De manera similar, las configuraciones de solo simulación podrían garantizar que las llamadas posteriores al subsistema hagan que genere una excepción , se cuelgue sin responder o regrese, nulletc. Por lo tanto, es posible desarrollar y probar comportamientos de clientes para condiciones de falla realistas en subsistemas de back-end , así como para sus respuestas esperadas. Sin un sistema de simulación tan simple y flexible, probar cada una de estas situaciones puede ser demasiado laborioso para que se les dé la debida consideración.

Escritura de cadenas de registro

Es posible que el método de un objeto de base de datos simulado save(person : Person)no contenga mucho código de implementación (si es que contiene alguno). Puede verificar la existencia y quizás la validez del objeto Persona que se pasó para guardar (consulte la discusión sobre falso vs. simulado más arriba), pero más allá de eso, es posible que no haya otra implementación.

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 haya realizado exactamente el número esperado de guardados de la base de datos. Esto puede encontrar errores que de otra manera serían invisibles y que minan el rendimiento, por ejemplo, donde un desarrollador, nervioso por perder datos, ha codificado llamadas repetidas donde save()una sola hubiera sido suficiente.

Uso en el desarrollo basado en pruebas

Los programadores que trabajan con el método de desarrollo impulsado por pruebas (TDD) hacen uso de objetos simulados al escribir software. Los objetos simulados cumplen con los requisitos de interfaz de los reales más complejos y los sustituyen; por lo tanto, permiten a los programadores escribir y probar unitariamente la funcionalidad en un área sin llamar a clases subyacentes complejas o colaboradoras . [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 los problemas de complejidad y los beneficios que se obtienen de esta separación de preocupaciones , existen problemas prácticos de velocidad. El desarrollo de un software realista utilizando TDD puede implicar fácilmente varios cientos de pruebas unitarias. Si muchas de ellas inducen la comunicación con bases de datos, servicios web y otros sistemas fuera de proceso o en red , entonces el conjunto de pruebas unitarias se volverá rápidamente demasiado lento para ejecutarse regularmente. Esto, a su vez, conduce a malos hábitos y a una renuencia por parte del desarrollador a mantener los principios básicos de TDD.

Cuando los objetos simulados se reemplazan por objetos reales, será necesario realizar más pruebas de la funcionalidad de extremo a extremo. Se tratará de pruebas de integración en lugar de pruebas unitarias.

Limitaciones

El uso de objetos simulados puede vincular estrechamente las pruebas unitarias a la implementación del código que se está probando. Por ejemplo, muchos marcos de trabajo de objetos simulados permiten al desarrollador verificar el orden y la cantidad de veces que los métodos de objetos simulados fueron invocados por el objeto real que se está probando; la refactorización posterior del código que se está probando podría, por lo tanto, hacer que la prueba falle aunque todos los métodos de objetos simulados sigan obedeciendo el contrato de la implementación anterior. Esto ilustra 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 en la cantidad de mantenimiento que se debe realizar en las pruebas mismas durante la evolución del sistema a medida que se realiza la refactorización. El mantenimiento inadecuado de dichas pruebas durante la evolución podría permitir que se pasen por alto errores que de otro modo serían detectados por pruebas unitarias que usan 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 están simulando, lo que puede ser difícil de lograr si el objeto que se está simulando proviene de otro desarrollador o proyecto o si ni siquiera se ha escrito todavía. Si el comportamiento no se modela correctamente, las pruebas unitarias pueden registrar un resultado satisfactorio aunque se produzca un error en el tiempo de ejecución en las mismas condiciones en las que se está ejercitando la prueba unitaria, lo que hace que la prueba unitaria sea inexacta. [10]

Véase también

Referencias

  1. ^ "Mejores prácticas de pruebas unitarias con .NET Core y .NET Standard: hablemos el mismo idioma (Fake, Stubs y Mocks)". Microsoft Docs . Archivado desde el original el 3 de septiembre de 2022.
  2. ^ D'Arcy, Hamlet (21 de octubre de 2007). "Los burlones y los esbirros no son espías". Behind the Times . Archivado desde el original el 20 de junio de 2017.
  3. ^ "Mocks, Fakes, Stubs and Dummies" (Simulacros, falsificaciones, esbozos y maniquíes). XUnitPatterns.com . Archivado desde el original el 17 de enero de 2024.
  4. ^ "¿Cuál es la diferencia entre un mock y un stub?". Stack Overflow . Archivado desde el original el 4 de julio de 2022.
  5. ^ "¿Cuál es la diferencia entre fingir, burlarse y burlarse?".
  6. ^ Feathers, Michael (2005). "Detección y separación". Cómo trabajar eficazmente con código heredado . Nueva Jersey: Prentice Hall. pág. 23 y siguientes. ISBN 0-13-117705-2.
  7. ^ Osherove, Roy (2009). "Pruebas de interacción con objetos simulados y demás". El arte de las pruebas unitarias . Manning. ISBN 978-1-933988-27-6.
  8. ^ Estos ejemplos utilizan una nomenclatura similar a la utilizada en el lenguaje de modelado unificado.
  9. ^ ab Beck, Kent (2003). Desarrollo basado en pruebas mediante ejemplos . Boston: Addison Wesley. ISBN 0-321-14653-0.
  10. ^ InJava.com para burlarse | O'Reilly Media

Enlaces externos