Mountebank – Customizando la configuración

0
185

Con este doy comienzo a una serie de artículos sobre Mountebank, como herramienta que nos va a permitir generar “test doubles” para mockear las llamadas de nuestras APIs, el objetivo que se persigue con esta serie de artículos es aprender a utilizar de la forma más práctica posible la herramienta de virtualización de servicios Mountebank con todas sus características y particularidades.

Aquí tienes la serie completa de tutoriales sobre Mountebank:

Entorno

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro 15′ (2,3 Ghz Intel Core i7, 16GB DDR4).
  • Sistema Operativo: Mac OS Catalina 10.15.5
  • Entorno de desarrollo: JDK 11, IntelliJ, Docker, Postman

 

Introducción

La estrategia que se seguirá en los artículos será enseñar la teoría para tener una idea de cuál sería el funcionamiento, e ir añadiendo, sobre un proyecto desde cero, los conceptos aprendidos mediante ejemplos que las cumplan.

Este artículo está dividido en 5 partes:

 

¿Qué es Mountebank?

Mountebank es una herramienta de virtualización de servicios que proporciona una API REST para crear y configurar servicios virtuales, que se denominan impostores. En lugar de configurar el servicio objeto de prueba para que apunte a las URLs de servicios reales, se configura para que apunte a los impostores que creamos a través de la API de Mountebank.

Dentro del ecosistema de herramientas de virtualización de servicios WireMock es probablemente la alternativa más popular a Mountebank, pero también existen otras herramientas como Hoverfly, Moco y stubby4j entre otras.

 

Cómo funciona Mountebank

Mountebank se centra en los impostores. Un impostor define cómo debe funcionar un servicio de mock. Cada impostor representa un socket que actúa como el servicio virtual. El primer trabajo del impostor es simplificar una petición específica de protocolo en una estructura JSON para que pueda comparar la petición con un conjunto de predicados.

Cada impostor se configura con una lista de stubs (comprobantes). Un stub devuelve una respuesta establecida basada en la solicitud, un stub no es más que una colección de una o más respuestas y, opcionalmente, una lista de predicados.

Para entender qué son y cómo funcionan los impostores es necesario conocer primero cómo se comunican los servicios, para ello vamos a ver un ejemplo de una petición HTTP y su respuesta y a continuación veremos cómo Mountebank la “traduce” a JSON para trabajar con los impostores más fácilmente.

Aquí podemos ver un ejemplo sencillo de petición/solicitud:

Donde la primera línea de cualquier petición HTTP contiene tres componentes: el método, la ruta, y la versión del protocolo.

En este ejemplo, se trata de una petición de tipo GET, que denota que se quiere recuperar información en lugar de intentar cambiar el estado de algún recurso del servidor. Su ruta es /courses, y está utilizando la versión 1.1 del protocolo HTTP.

La segunda línea inicia los encabezados (headers), que son un conjunto de nuevos pares de valores clave separados por líneas.

En el ejemplo, vemos que tenemos el encabezado Host que se combina con la ruta y el protocolo para dar la URL completa como se vería en un navegador: http://api.autentia.com/courses. El encabezado Accept le indica al servidor que está esperando que devuelva JSON.

En cuanto a las respuestas, es bastante similar.

La primera línea de la respuesta contiene los metadatos, donde el código de estado/respuesta es el más importante. Las cabeceras (headers) siguen una vez más a los metadatos y en último lugar el cuerpo (body) que siempre está separado de los encabezados por una línea vacía.

Mountebank traduce los campos del protocolo de aplicación HTTP a JSON tanto para las solicitudes como para las respuestas, en el siguiente ejemplo podemos ver como se encuentran claramente distinguidas propiedades que hemos visto de la llamada HTTP como pueden ser el método, el path, el body, etc, dentro de la estructura JSON del impostor.

¿Y entonces, cómo es el proceso que realiza exactamente Mountebank cuando recibe una solicitud?

Mountebank pasa la solicitud a cada stub en orden de lista y escoge el primero que coincida con todos los predicados. Si la solicitud no coincide con ninguno de los stubs definidos, mountebank devuelve una respuesta predeterminada. De lo contrario, devuelve la primera respuesta para ese stub. Siguiendo con nuestro ejemplo, podemos ver que frente a un impostor como el siguiente Mountebank nos devolverá la primera respuesta del segundo stub.

 

«Dockerizando» Mountebank

Desde mi punto de vista una de las formas más sencillas de trabajar con Mountebank dentro de nuestros servicios Java es la que os voy a comentar ya que no sería necesario realizar instalaciones manuales mediante node y arrancar manualmente nuestro servidor de mocks de Mountebank.

Hasta la versión 2.2.0, Mountebank no disponía de una imagen oficial docker por lo que lo más sencillo era crear nuestra propia imagen a partir del siguiente Dockerfile y subirlo a nuestro repositorio de imágenes:

Con el siguiente comando construimos nuestra imagen de Mountebank customizada:

Con el siguiente comando “taggeamos” nuestra imagen antes de subirla al repositorio:

Y por último, la subimos a nuestro repositorio:

Una vez que tenemos la imagen alojada en nuestro repositorio, vamos a crear dentro de nuestro servicio un docker-compose que configuraremos con dicha imagen y que al arrancar levante nuestro servidor de Mountebank.

Como he comentado anteriormente desde la versión 2.2.0 es posible crear nuestro docker-compose configurando la imagen oficial de Mountebank, dando como resultado el siguiente archivo:

 

Probando nuestra configuración

Como ya hemos comentado anteriormente podemos crear nuestros impostores usando la API RESTful de Mountebank o a través de configuración si nos fijamos en nuestro docker-compose previo podemos observar que hemos configurado nuestro servidor de Mountebank para que lea del directorio mountebank de nuestro proyecto, por lo que bastaría con configurar en dicho archivo nuestros impostores antes de levantar el servidor.

Vamos a verlo con un ejemplo, creamos una carpeta dentro de ‘src/test/resources’ que se llame mountebank, dentro de ella vamos a crear el archivo ‘service.ejs’ con el siguiente contenido:

Configurado nuestro impostor, vamos a levantar nuestro contenedor con la imagen del servidor Mountebank con el siguiente comando:

Para probar nuestro impostor bastaría con ejecutar el siguiente curl, donde estamos simulando la llamada a nuestro servicio real de cursos pero invocando a nuestro servicio virtualizado de Mountebank en el puerto 80 definido anteriormente.

Como podéis observar obtenemos la respuesta que configuramos en nuestro impostor:

A partir de este momento cualquier llamada que hagamos al servicio de cursos desde nuestro servicio va a ser interceptada por Mountebank, el cual va a devolver la respuesta que hayamos configurado, decimos que “entrenamos” a Mountebank para que simule el servicio real.

 

Conclusiones

En este artículo hemos repasado de forma muy práctica cómo configurar nuestro servidor de Mountebank que puede ayudarnos en nuestro día a día con nuestros tests de microservicios.

Puedes descargar el proyecto completo aquí.

 

Referencias

http://www.mbtest.org/

https://github.com/bbyars/mountebank

https://github.com/bbyars/mountebank-in-action

https://hub.docker.com/r/bbyars/mountebank

Dejar respuesta

Please enter your comment!
Please enter your name here