Soy nuevo en las pruebas unitarias y escucho continuamente las palabras "objetos simulados". En términos simples, ¿alguien puede explicar qué son los objetos simulados y para qué se usan típicamente al escribir pruebas unitarias?
unit-testing
mocking
agentbanks217
fuente
fuente
Respuestas:
Como usted dice que es nuevo en las pruebas unitarias y que solicita objetos simulados en "términos simples", intentaré con un ejemplo simple.
Examen de la unidad
Imagine pruebas unitarias para este sistema:
En general, es fácil imaginar probar un componente de bajo nivel como
cook
:El conductor de prueba simplemente ordena diferentes platos y verifica que el cocinero devuelva el plato correcto para cada pedido.
Es más difícil probar un componente intermedio, como el camarero, que utiliza el comportamiento de otros componentes. Un probador ingenuo podría probar el componente de camarero de la misma manera que probamos el componente de cocción:
El conductor de prueba pediría diferentes platos y se aseguraría de que el camarero devuelva el plato correcto. Desafortunadamente, eso significa que esta prueba del componente de camarero puede depender del comportamiento correcto del componente de cocción. Esta dependencia es aún peor si el componente de cocción tiene características poco amigables con la prueba, como un comportamiento no determinista (el menú incluye la sorpresa del chef como plato), muchas dependencias (el cocinero no cocinará sin todo su personal) o muchos recursos (algunos platos requieren ingredientes caros o tardan una hora en cocinarse).
Dado que esta es una prueba de camarero, idealmente, queremos probar solo al camarero, no al cocinero. Específicamente, queremos asegurarnos de que el camarero transmita el pedido del cliente al cocinero correctamente y entregue la comida del cocinero al cliente correctamente.
La prueba de unidad significa probar unidades de forma independiente, por lo que un mejor enfoque sería aislar el componente bajo prueba (el camarero) utilizando lo que Fowler llama dobles de prueba (maniquíes, trozos, falsificaciones, simulacros) .
Aquí, el cocinero de prueba está "confabulado" con el conductor de prueba. Idealmente, el sistema bajo prueba está diseñado para que el cocinero de prueba pueda ser fácilmente sustituido ( inyectado ) para trabajar con el camarero sin cambiar el código de producción (por ejemplo, sin cambiar el código del camarero).
Objetos simulados
Ahora, la prueba de cocción (prueba doble) podría implementarse de diferentes maneras:
Vea el artículo de Fowler para obtener más detalles sobre falsificaciones vs trozos vs simulacros vs tontos , pero por ahora, centrémonos en un simulador de cocina.
Una gran parte de la unidad que prueba el componente de camarero se centra en cómo interactúa el camarero con el componente de cocción. Un enfoque basado en simulacro se centra en especificar completamente cuál es la interacción correcta y detectar cuándo sale mal.
El objeto simulado sabe de antemano qué se supone que sucederá durante la prueba (por ejemplo, cuál de sus métodos se invocarán las llamadas, etc.) y el objeto simulado sabe cómo se supone que reaccionará (por ejemplo, qué valor de retorno proporcionar). El simulacro indicará si lo que realmente sucede difiere de lo que se supone que debe suceder. Se podría crear un objeto simulado personalizado desde cero para cada caso de prueba para ejecutar el comportamiento esperado para ese caso de prueba, pero un marco de simulación se esfuerza por permitir que dicha especificación de comportamiento se indique clara y fácilmente directamente en el caso de prueba.
La conversación en torno a una prueba simulada podría verse así:
Pero como nuestro camarero es nuevo, esto es lo que podría suceder:
o
Puede ser difícil ver claramente la diferencia entre objetos simulados y trozos sin un ejemplo contrastante basado en trozos para ir con esto, pero esta respuesta ya es demasiado larga :-)
También tenga en cuenta que este es un ejemplo bastante simplista y que los marcos de imitación permiten algunas especificaciones bastante sofisticadas del comportamiento esperado de los componentes para admitir pruebas exhaustivas. Hay mucho material sobre objetos simulados y marcos burlones para obtener más información.
fuente
Un objeto simulado es un objeto que sustituye a un objeto real. En la programación orientada a objetos, los objetos simulados son objetos simulados que imitan el comportamiento de los objetos reales de manera controlada.
Un programador de computadora generalmente crea un objeto simulado para probar el comportamiento de algún otro objeto, de la misma manera que un diseñador de automóviles usa un maniquí de prueba de choque para simular el comportamiento dinámico de un humano en los impactos de vehículos.
http://en.wikipedia.org/wiki/Mock_object
Los objetos simulados le permiten configurar escenarios de prueba sin tener que soportar recursos grandes y difíciles de manejar, como bases de datos. En lugar de llamar a una base de datos para realizar pruebas, puede simular su base de datos utilizando un objeto simulado en sus pruebas unitarias. Esto lo libera de la carga de tener que configurar y destruir una base de datos real, solo para probar un método único en su clase.
La palabra "simulacro" a veces se usa erróneamente de manera intercambiable con "trozo". Las diferencias entre las dos palabras se describen aquí. Esencialmente, un simulacro es un objeto auxiliar que también incluye las expectativas (es decir, "aserciones") para el comportamiento adecuado del objeto / método bajo prueba.
Por ejemplo:
Observe que los objetos simulados
warehouse
ymailer
están programados con los resultados esperados.fuente
Los objetos simulados son objetos simulados que imitan el comportamiento de los reales. Por lo general, escribe un objeto simulado si:
fuente
Un objeto simulado es un tipo de prueba doble . Está utilizando mockobjects para probar y verificar el protocolo / interacción de la clase bajo prueba con otras clases.
Por lo general, tendrá una especie de 'programa' o 'registro' de expectativas: llamadas de método que espera que su clase le haga a un objeto subyacente.
Digamos, por ejemplo, que estamos probando un método de servicio para actualizar un campo en un widget. Y que en su arquitectura hay un WidgetDAO que se ocupa de la base de datos. Hablar con la base de datos es lento y configurarlo y limpiarlo después es complicado, por lo que nos burlaremos del WidgetDao.
pensemos qué debe hacer el servicio: debe obtener un widget de la base de datos, hacer algo con él y guardarlo nuevamente.
Entonces, en pseudo-idioma con una biblioteca de pseudo-simulacro, tendríamos algo como:
De esta manera, podemos probar fácilmente el desarrollo de clases que dependen de otras clases.
fuente
Recomiendo encarecidamente un gran artículo de Martin Fowler que explique qué son exactamente los simulacros y en qué se diferencian de los trozos.
fuente
Cuando la unidad prueba alguna parte de un programa de computadora, lo ideal es probar solo el comportamiento de esa parte en particular.
Por ejemplo, mire el pseudocódigo siguiente de una pieza imaginaria de un programa que usa otro programa para llamar a print algo:
Si estuviera probando esto, principalmente querría probar la parte que analiza si el usuario es Fred o no. Realmente no quieres probar la
Printer
parte de las cosas. Esa sería otra prueba.Aquí es donde entran los objetos simulados. Pretenden ser otro tipo de cosas. En este caso, usaría un Mock
Printer
para que actuara como una impresora real, pero no haría cosas inconvenientes como imprimir.Hay varios otros tipos de objetos de simulación que puede usar que no son simulacros. Lo principal que hace que Mocks Mocks es que se pueden configurar con comportamientos y expectativas.
Las expectativas le permiten a tu simulacro generar un error cuando se usa incorrectamente. Entonces, en el ejemplo anterior, puede estar seguro de que se llama a la impresora con HelloFred en el caso de prueba "el usuario es Fred". Si eso no sucede, tu Mock puede advertirte.
Comportamiento en simulacros significa que, por ejemplo, su código hizo algo como:
Ahora desea probar qué hace su código cuando se llama a la Impresora y devuelve SaidHello, de modo que puede configurar el Mock para que devuelva SaidHello cuando se llama con HelloFred.
Un buen recurso en torno a esto es Martin Fowlers post Mocks An't Stubs
fuente
Los objetos simulados y trozos son una parte crucial de las pruebas unitarias. De hecho, hacen un largo camino para asegurarse de que esté probando unidades , en lugar de grupos de unidades.
En pocas palabras, usa stubs para romper la dependencia de SUT (Sistema bajo prueba) en otros objetos y simulacros para hacer eso y verificar que SUT haya llamado ciertos métodos / propiedades en la dependencia. Esto se remonta a los principios fundamentales de las pruebas unitarias: que las pruebas deben ser fáciles de leer, rápidas y no requieren configuración, lo que puede implicar el uso de todas las clases reales.
En general, puede tener más de un trozo en su prueba, pero solo debe tener un simulacro. Esto se debe a que el propósito del simulacro es verificar el comportamiento y su prueba solo debe probar una cosa.
Escenario simple usando C # y Moq:
En el ejemplo anterior, utilicé Moq para demostrar trozos y simulacros. Moq usa la misma clase para ambos,
Mock<T>
lo que lo hace un poco confuso. Independientemente, en tiempo de ejecución, la prueba fallará sioutput.Write
no se llama con datos comoparameter
, mientras que la falla en la llamadainput.Read()
no fallará.fuente
Como sugirió otra respuesta a través de un enlace a "Los simulacros no son trozos ", los son una forma de "prueba doble" para usar en lugar de un objeto real. Lo que los hace diferentes de otras formas de dobles de prueba, como los objetos de código auxiliar, es que otros dobles de prueba ofrecen verificación de estado (y opcionalmente simulación) mientras que los simulacros ofrecen verificación de comportamiento (y opcionalmente simulación).
Con un apéndice, puede llamar a varios métodos en el apéndice en cualquier orden (o incluso de forma repetitiva) y determinar el éxito si el apéndice ha capturado un valor o estado que deseaba. En contraste, un objeto simulado espera que se invoquen funciones muy específicas, en un orden específico e incluso un número específico de veces. La prueba con un objeto simulado se considerará "fallida" simplemente porque los métodos se invocaron en una secuencia o recuento diferente, ¡incluso si el objeto simulado tenía el estado correcto cuando concluyó la prueba!
De esta manera, los objetos simulados a menudo se consideran más estrechamente acoplados al código SUT que los objetos de código auxiliar. Eso puede ser algo bueno o malo, dependiendo de lo que intente verificar.
fuente
Parte del punto de usar objetos simulados es que no tienen que implementarse realmente de acuerdo con las especificaciones. Solo pueden dar respuestas ficticias. Por ejemplo, si tiene que implementar los componentes A y B, y ambos "se llaman" (interactúan) entre sí, entonces no puede probar A hasta que se implemente B, y viceversa. En el desarrollo basado en pruebas, este es un problema. Entonces creas objetos simulados ("ficticios") para A y B, que son muy simples, pero dan algún tipo de respuesta cuando interactúan con ellos. De esa manera, puede implementar y probar A usando un objeto simulado para B.
fuente
Para php y phpunit se explica bien en phpunit documentaion. ver aquí la documentación de phpunit
En palabras simples, el objeto de burla es solo un objeto ficticio del original y devuelve su valor de retorno, este valor de retorno se puede usar en la clase de prueba
fuente
Es una de las principales perspectivas de las pruebas unitarias. Sí, está intentando probar su única unidad de código y los resultados de su prueba no deberían ser relevantes para el comportamiento de otros beans u objetos. por lo tanto, debe burlarse de ellos utilizando objetos Mock con alguna respuesta correspondiente simplificada.
fuente