Introducción a Mountebank para la creación de servidores dobles de test

En este tutorial haremos una introducción a la herramienta Mountebank para la creación de servidores que actúen como dobles de test (mock servers) de correo electrónico y de HTTP para ser utilizados en tests de una aplicación Java

0. Índice de contenidos


1. Introducción

En muchas ocasiones resulta util tener la posibilidad de utilizar servidores simulados para realizar pruebas de nuestras aplicaciones. La herramienta open source Mounteback permite la creación y configuración de forma sencilla de servidores que actúen como dobles de test en dichas pruebas. La versión 1.2.122 utilizada en este tutorial permite simular servidores que utilicen los protocolos SMTP, HTTP, HTTPS y TCP.

El objetivo de este tutorial es crear unos sencillos ejemplos que permitan ver las capacidades de esta herramienta desde una aplicación Java


2. Entorno

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro Retina 15′ (2.5 Ghz Intel Core i7, 16GB DDR3).
  • Sistema Operativo: Mac OS Yosemite 10.10.5
  • Entorno de desarrollo: Eclipse Mars 4.5.0
  • Gestión de dependencias: Apache Maven 3.3.3
  • Java: JDK 1.8
  • Mountebank: Self-contained archives 1.2.122

3. Instalación y puesta en marcha del servidor Mountebank

Mountbank es una herramienta open source para la creación de servidores dobles de test que corre sobre un servidor node.js 0.10. Se puede instalar como un componente de un servidor existente o descargar en una versión empaquetada que ya incluye dicho servidor embebido. Cualquier opción es igualmente válida, pero para no complicar en exceso este tutorial, utilizaremos la versión embebida.

Para hacer funcionar dicha versión hay que descomprimir el fichero que podemos descargar de la página web de mountebank (http://www.mbtest.org/y ejecutar el comando “mb” que hay en su interior. Si todo va bien, veremos un mensaje similar a este en la consola, indicando que el servidor está listo para recibir peticiones

En este momento nuestro servidor está preparado para escuchar. Ahora, debemos cargar los dobles de test en el servidor. Estos dobles de test son llamados imposters. La forma de configurar dichos imposters es mediante una sencilla interfaz REST que ofrece el servidor mounteback instalado en el puerto 2525. La interfaz nos ofrece los típicos servicios CRUD (acrónimo de Crear, Leer, Actualizar y Borrar, por sus siglas en inglés) en el path “/imposters”

Para crear un imposter se debe utilizar el método POST, adjuntando la definición de dicho servidor en formato JSON. Según la documentación de la API, el único atributo obligatorio sería “protocol”, sin embargo es recomendable incluir también el puerto, ya que en caso contrario, mountebank creará el servidor en un puerto aleatorio, y esto, dado que el método POST no garantiza la entrega, puede ser un problema que genere duplicados en el servidor si se lanzan reintentos tras un timeout. Con esto, una definición básica de un servidor doble de test quedaría de la siguiente forma:

La definición anterior generaría un servidor doble de test que responda al protocolo HTTP en el puerto 8484, cuya respuesta ante cualquier petición sería un cuerpo vacío con código de estatus 200. Para probar la funcionalidad de dicho servidor habría que hacer una llamada en el path “/test”.

Una vez creado el servidor, este queda registrado en el path “/imposters/PUERTO“, donde PUERTO sería 8484 en el ejemplo anterior. Este path será el utilizado si se quiere consultar los detalles del servidor usando GET o borrarlo usando DELETE. La opción de actualizarlo no está disponible para servidores individuales, quedando sólo la opción de actualizar todos los imposters a la vez usando PUT desde el path “/imposters”.

Estos imposters se podrían crear de forma externa a la aplicación utilizando una herramienta como “curl”. Sin embargo, para aumentar la automatización de los test, vamos a integrar la creación de los servidores dobles de test en nuestra aplicación, una vez creados se realizarán los test correspondientes y al finalizar, los imposters serán eliminados.


4. Configuración del proyecto Java

Este tutorial utiliza un proyecto Java haciendo uso de Maven como gestor de dependencias y compilación. El fichero “pom.xml” queda de la siguiente forma:


5. Test de integración con un servidor SMTP doble de test

En este apartado vamos a ver cómo crear un servidor SMTP doble de test. En este caso vamos a crear una sencilla clase de Java encargada de enviar un correo. En un entorno real la lógica de negocio sería más compleja, pero se ha pretendido mostrar la configuración lo más sencilla posible para centrar el interés en la parte de mountebank.

ExampleEmailSender.java

A continuación se muestra el código de la clase de test donde se prueba la funcionalidad de la clase de negocio:

ExampleEmailSenderTest.java

En la clase anterior se puede ver como se realizan las siguientes acciones:

  • Se instancia un MountebankHandler para el manejo del servidor de mountebank en un método de iniciación común a todos los tests.
  • Se lee la configuración del servidor de pruebas que se va a generar
  • Se crea un email de test y se intenta enviar
  • Se obtiene el valor actual del Imposter del servidor, con el objetivo de validar que se haya producido el envío del correo correctamente en el servidor
  • Se comprueba que el array de peticiones del servidor no es nulo
  • Se comprueba que el array de peticiones no esté vacío
  • Se comprueba que en la primera entrada del array de peticiones, la dirección de correo electrónico desde la que se ha enviado el correo coincide con la esperada. Se podría conseguir una solución más elegante definiendo el atributo MountebankImposter.requests como un List<MountebankRequest>, para lo cual habría que definir la clase MountebankRequest con todos los posibles valores definidos por el API, y de hecho sería la opción más recomendable en un entorno real, pero para no complicar en exceso este tutorial, se ha dejado como aparece en el código, lo que genera un warning en la linea donde se define la variable “emailFrom”
  • Finalmente, se elimina el servidor de pruebas que se ha creado y se cierra el manejador de mountebank

El fichero “SMTPImposter.json” al que se hace referencia en el código se encuentra en una carpeta incluida en el classpath de java y su contenido es el siguiente:

SMTPImposter.json

Además, se muestra a continuación el código de la clase MountebankHandler y MountebankImposter. La clase MountebankHandler se encarga de la creación y eliminación del servidor de pruebas dentro de mountebank, mientras que la clase MountebankImposter se trata de una clase cuyo objetivo es la representación en la aplicación de los objetos de configuración de mountebank.

MountebankHandler.java
MountebankHandler.java

para ejecutar el test, lanzamos maven con el goal “test”, y si todo va bien veremos que el test pasa sin problemas.

Adicionalmente, se puede ver en la ventana de comandos donde se está ejecutando mountebank algo similar a lo siguiente:

En el log anterior se puede ver cómo mountebank ha creado un servidor SMTP en el puerto 4547, cómo se ha generado un correo electrónico y cómo se ha borrado el servidor.


6. Test de integración con un servidor HTTP doble de test

A continuación veremos como crear un test para probar un cliente HTTP utilizando un servidor doble de test creado con mountebank. En este caso la tarea va a llevarnos menos tiempo, ya que ya tenemos definidas las clases MountebankHandler y MountebankImposter.

Supongamos que tenemos una clase de negocio como la siguiente:

ExampleHttpClient.java

El test que tenemos que definir para dicho cliente asume que el recurso que se va a obtener es siempre la cadena “OK” en formato texto plano ante peticiones GET. Para probar dicho cliente empezamos definiendo el fichero de configuración del servidor, que quedaría de la siguiente forma:

Esta configuración define un “stub” que hace que el servidor responda usando el protocolo HTTP sobre el puerto 8484. La respuesta siempre será “OK”, con código de estatus 200. Si por ejemplo quisiéramos testear un cliente que crea objetos en el servidor mediante el método POST, tendríamos que simular que en la primera petición el objeto se haya creado (devolviendo estatus 201) y devolviendo error en las siguientes peticiones sobre el mismo recurso puesto que se supone que ya existiría. Para ello, bastaría con añadir más objetos dentro del array “responses”, teniendo en cuenta que las respuestas se irán entregando en el mismo orden en el que aparezcan definidas en el objeto JSON. Además, se podrían incluir encabezados en la respuesta tales como “Content-Type” o “Location”.

Una vez definido la configuración del servidor de pruebas, modificamos la clase de test para incorporar la lógica de arranque y parada del servidor de pruebas de Mountebank, quedando el código de la siguiente forma:

ExampleHttpClientTest.java

Una vez tenemos todo listo, ejecutamos el goal “test” de maven y el resultado debería ser similar al siguiente:


7. Conclusiones

En este tutorial hemos visto como instalar y configurar la herramienta Mountebank para crear servidores de pruebas para nuestros tests. Para entender mejor su funcionamiento hemos realizado una serie de ejemplos en Java utilizando Maven. El primer ejemplo presenta una configuración básica basada en el envío de un correo electrónico y posteriormente un ejemplo algo más complejo probando un cliente HTTP.


8. Referencias