leanmind logo leanmind text logo

Blog

Refactorización Avanzada

Dominar el refactoring productivo para maximizar el retorno de la inversión.

Los Mocks estrictos son una herramienta de diseño de software

Por Mario S. Pinto Miranda

Este artículo surge a raíz de un debate sobre las soluciones generadas en la kata Mouse Events en las sesiones de formación de Lean Mind. Para resolver esta kata es necesario usar dobles de test, pues no hay exposición del estado interno del artefacto Mouse. Los dobles de test que se ajustaban al caso son, en la terminología expuesta por Gerad Meszaros, el doble Spy y el Mock escricto. Hubo argumentos a favor y en contra de usar uno u otro. Se defendía que el Spy permitía más cadencia de desarrollo y flexibilidad, mientras que el Mock aseguraba más confiabilidad de que todas las precondiciones necesarias/esperadas ocurrirían. Sobre esto último, se expuso que hacía que los tests fueran más frágiles ante cambios futuros, pues fija cómo deberán ser las interacciones entre objetos, de modo que, ante posibles cambios de estos, los tests se volverían un lastre. Sin embargo, hubo un argumento expuesto que puso sobre la mesa una dimensión, que al menos por mi parte, no había meditado. Este fue algo similar a:

“A lo mejor ese cambio futuro no debería ser sobre ninguno de los objetos que ya ha sido probado con Mocks estrictos, si los tests fallan puede ser un indicativo que esa nueva funcionalidad no encaja ahí, si se han establecido expectativas desde un punto de vista de diseño, este no debería ser modificado, sino extendido”.

¿Qué hay detrás del argumento? ¡Veámoslo!

El orígen

El argumento fue expuesto por Carlos Blé a raíz de una entrada de blogpost de J.B. Rainsberger (”JMock v. Mockito, but not to the death”). En este, el autor expone dos ideas fundamentales:

Estos argumentos son contundentes pero echaba en falta más fundamentos para que tuviesen el peso suficiente para respaldar la tesis: “ Los Mocks estrictos son una herramienta de diseño”.

Fundamentos

El software como una red de interacción de objetos

En el diseño de software, con programación orientada a objetos (POO), tiene realmente más importancia cómo los objetos (que componen un software/sistema) se comunican, qué cómo están diseñados estos individualmente porque el comportamiento de un software surge/emerge de la interacción entre estos. Por tanto, adoptar este enfoque, orientado al comportamiento del sistema, implica que desarrollo se debe centrar en cómo se construye la red de comunicación de objetos. El beneficio principal es el desarrollo de objetos que son fácilmente conectables con otros, es decir, que siguen los patrones de comunicación comunes y las dependencias son explícitas. Estos patrones se basan en trabajar con los objetos bajo relaciones de Roles, Responsabilidades, y Colaboraciones. Para entender esto te expongo lo que se entiende con los anteriores términos:

De esta manera, el diseño se centraría en desarrollar objetos definiéndoles un/os rol/es con unas responsabilidades y unos colaboradores necesarios para cumplir con estas. Para este tipo de diseño se suelen aplicar Tarjetas CRC (Candidates, Resposabilities and collaborators).

Por otro lado, al desarrollar software con POO, deberíamos evitar exponer el estado interno de los objetos con el fin de:

Esto se puede conseguir evitando preguntar por información a los objetos y con esta generar un resultado, sino diciéndoles que tienen que hacer para generar el resultado por paso de un mensaje (invocación de un método). Esto, a un nivel de diseño más alto, debería traducirse en “un objeto debería describir lo que quiere de sus colaboradores, actuando estos con un rol determinado”. En definitiva, se consigue hacer explícita qué interacción se ha de producir, más en cómo se produce. Ahora bien, ¿Cómo testeamos esto?

Testing de la colaboración de objetos

Para realizar testing sobre artefactos es necesario un punto de observación. El caso sobre un único objeto es simple: se observa que ante unos inputs dados (sobre un punto de entrada accesible), se produzca un resultado esperado (el cual también es accesible), como si de una caja negra se tratara. Sin embargo, cuando se trata de testar la colaboración entre objetos, esta puede no tener ni la entrada de información ni la salida expuesta, un punto de observación accesible. Además, puede ser necesaria que ocurran varias entradas y salidas de información entre los objetos para poder verificar un comportamiento.

No deberíamos exponer estados internos de los objetos para tener un punto de observación tal y cómo se comentaba antes, de modo que una estrategia para lidiar con esto es el uso de dobles de test. Si atendemos, a todos los posibles dobles que expone Gerad Meszaros, los más adecuados son los mocks estrictos y los fake objects. El primero permite verificar que las interacciones se producen correctamente para que surja el comportamiento esperado del sistema y el segundo es una implementación simplificada de una real que permite exponer puntos de observación. El problema de usar el segundo es que obliga a mantener un artefacto no productivo para poder seguir manteniendo operativos los test ya creados más soportar otros futuros. En cambio, los mock objects solo tienen una misión: asegurar que el colaborador y el artefacto bajo test interactúen correctamente bajo un lenguaje declarativo de expectativas, el cual se abstrae de cómo es la lógica ejecutable por el paso de mensaje entre objetos. En el caso de que el mock object deba devolver valores, estos también se declaran si se cumple la secuencia.

Otros dobles como los Spy o los Stub permiten evidenciar comportamientos del sistema solo de forma parcial y pueden servir como soporte cuando representan objetos que no son el foco principal o no tienen una interacción. Aunque cabría preguntarse si se hace esto, ¿No será que ese colaborador no está bien planteado? Como la discusión puede quedarse en los grises, podemos dejarlo solo en la pregunta

Conclusiones

Los Mocks estrictos son una herramienta de diseño porque permiten establecer, antes de desarrollar cada objeto individualmente, cómo van a interaccionar, es decir, permiten diseñar el comportamiento del sistema, que es el foco principal de la POO en el desarrollo de software.

Agradecimientos

A Lean Mind, a todo el equipo, de dar la posibilidad a sesiones donde surgen debates que plantan la semilla de la curiosidad.

Referencias

Publicado el 26/06/2023 por

¿Quieres más? te invitamos a suscribirte a nuestro boletín para avisarte cada vez que recopilemos contenido de calidad que compartir.

Si disfrutas leyendo nuestro blog, ¿imaginas lo divertido que sería trabajar con nosotros? ¿te gustaría?

Impulsamos el crecimiento profesional de tu equipo de developers