Los MockServer son herramientas que nos permiten simular respuestas HTTP, evitando la necesidad de configurar un aplicativo original para consumir los recursos necesarios.
¿Donde sería útil usar un MockServer?
En desarrollos tempranos donde tener un API operable puede tardar semanas o meses.
Si el aplicativo a consumir es demasiado complejo para ambientarlo localmente.
En arquitecturas de microservicios. Debido a que muchos aplicativos interactúan entre si para un solo objetivo, puede ser necesario ambientar más de uno localmente, lo cual es costoso muchas de las veces.
Mockserver vs Aplicativo original
Ambientar los aplicativos localmente a veces llevan su tiempo, ya que puede involucrar desde temas técnicos como de negocio.
Para el caso técnico involucra desde configuración de dependencias, configuración de permisos, creación de usuarios, configuración de base de datos, etc. Por otro lado, en temas de negocio debemos de conocer las reglas de negocio, por ejemplo, si un recurso se encuentra en tal estado es porque debe de tener un estatus x y que ademas este asociado a otro recurso y que ese recurso deba de tener valores no nulos en tres de sus propiedades.
Todo esto hace que ambientar una aplicación localmente sea costoso. Sin embargo, no quiero decir que no sea importante conocer los temas técnicos y de negocio, solo debería ser abordado gradualmente.
Teniendo un poco más de contexto sobre los MockServer saltemos a un ejemplo práctico.
Para este ejemplo, vamos a utilizar Mockoon https://mockoon.com/ como MockServer.
Generalmente, los MockServer tienen funcionalidades similares. Esto hace que aprender uno facilite aprender los otros.
Se nos mostrará un demo donde se resaltan tres secciones importantes.
Rojo. Listado de ambientes locales.
Rosa. Listado de routes.
Blanco. Configuración de una route.
3. Creamos nuestro ambiente local.
Para este ejemplo, vamos a crear un nuevo ambiente local el cual va a simular un microservicio de pagos, escuchando en el puerto 8001 y con un endpoint /orders de tipo GET que regresa un array de órdenes.
Al hacer clic, nos generara un archivo .json, este archivo almacena la configuración de todo lo que hagamos dentro de la interfaz gráfica.
4. Creamos y configuramos nuestra route orders.
5. Configuración de puerto
6. Encendemos aplicativo local
7. Consultamos el endpoint.
En cuestión de minutos habilitamos un MockServer listo para usarse y nos evitamos dolores de cabeza en ambientar el aplicativo original.
Ahora bien, nuestro siguiente paso es usarlo. Para esto, vamos a imaginar el siguiente caso de uso.
Necesitamos un formulario que permita seleccionar una orden, insertar un nombre de cliente. En caso de que la orden ya se haya asociado a un cliente, mostrar un mensaje de error.
Paso 1. Comencemos creando nuestro proyecto.
npx create-react-app my-app
cd my-app
npm start
Paso 2. Ataquemos el problema desde un enfoque de pruebas. Lo primero es crear nuestro archivo de prueba.
src/CreateOrder.test.js
1: describe('CreateOrder', () => {
2: it('crear orden correctamente', () => {
3:
4: });
5:
6: it('si la orden ya fue asignada mostrar mensaje de error', () => {
7:
8: });
9: });
Paso 3. Resolvamos la primera prueba “crear orden correctamente”.
😭 Otro error. No esta encontrado el elemento con la propiedad data-testid=“customer” y esta en lo correcto, porque el componente esta vació. Solucionemos esto.
Paso 7. Implementemos la solución para la prueba “crear orden correctamente”.
Línea 21..27. En caso de error, guardamos el error.
Línea 57. Mostramos el error en caso de estar definido.
Paso 12. Ejecutemos la prueba.
🤞🏼Lo logramos, nuestras pruebas pasaron correctamente. Sin embargo, si levantamos el proyecto no podremos ver el comportamiento esperado de las pruebas porque no hemos definido los endpoints que recibe como prop nuestro componente.
Aquí es donde entra en acción nuestro MockServer que acabamos de crear. Al inicio creamos nuestro primer endpoint /orders que nos va a servir para listar las órdenes como en la prueba. Pero que sucede con el caso de si existe un usuario asociado a una orden, ¿cómo podemos replicarlo? ¿Existe alguna funcionalidad en nuestro MockServer que nos ayude?
Los MockServers nos permiten definir respuesta con base en ciertas condiciones. Veamos como lograrlo.
Paso 11. Definimos una ruta encargada de regresar un estatus ok cuando ingresemos un nombre diferente a Gabriel.
Paso 12. Definamos una ruta encargada de regresar un estatus failed cuando mandemos el valor Gabriel.
Paso 13. Montamos nuestro componente en la raíz del proyecto.
Línea 3..5. Endpoint para traer la información de las órdenes
Línea 7..18. Endpoint para simular el guardado de nuestra orden.
Línea 20..22. Componente App
Paso 14. Levantamos nuestra aplicación frontend así como nuestro MockServer
Al iniciar nuestro frontend vemos que nos esta regresando la data de nuestro MockServer y pinta las órdenes correctamente.
Paso 15. Ahora guardemos una orden con un cliente con una orden asociada. Nos debería de arrojar un error como lo vimos en en nuestras pruebas.
Ups, creo que hubo un error. Esto sucede porque el <form> tiene dos propiedades action y method y no hemos definido ningún valor, entonces, como action se esta tomando la página actual y en el method por defecto toma el get, es por eso que vemos la url localhost:3000/?customer=Gabriel&order=1.
Para evitar esto, hay que prevenir este comportamiento.
Al ejecutar nuestras pruebas en un ambiente no real puede ocasionar este tipo de problemas. Sin embargo, te aseguro que la cantidad de errores será menor.
Podemos ver que el MockServer esta respondiendo conforme al paso 12.
Paso 16. Por último, vamos a crear una orden con un cliente sin una orden asociada.
Perfecto, nuestro MockServer esta respetando las reglas que definimos.
Conclusión
Los MockServers son herramientas poderosas que nos permiten replicar comportamientos esperados basados en diferentes reglas de negocio, como vimos en nuestro ejemplo.
Además, las pruebas nos permiten comenzar a desarrollar la lógica sin tener ni quiera un ambiente local original o un MockServer.
Evitar distracciones que no nos competen dentro de nuestro rol, nos permitirá enfocarnos y desarrollar aplicaciones más escalables.