# Simulación de servicios API en desarrollo y pruebas con WireMock


Durante el desarrollo local y las pruebas, es bastante común encontrarse con situaciones en las que tu aplicación depende de APIs remotas. Los problemas de red, los límites de velocidad o incluso la inactividad del proveedor de la API pueden detener tu progreso. Esto puede obstaculizar significativamente tu productividad y hacer que las pruebas sean más difíciles. Aquí es donde entra en juego WireMock.

WireMock es una herramienta de código abierto que ayuda a los desarrolladores a crear un servidor simulado que imita el comportamiento de las APIs reales, proporcionando un entorno controlado para el desarrollo y las pruebas.

Imagina que tienes tanto una API como una aplicación frontend, y deseas probar cómo interactúa el frontend con la API. Con WireMock, puedes configurar un servidor simulado para imitar las respuestas de la API, lo que te ayuda a probar el comportamiento del frontend sin depender de la API real. Esto puede ser especialmente útil cuando la API aún está en desarrollo o cuando deseas probar diferentes escenarios sin afectar a la API real. WireMock admite protocolos HTTP y HTTPS y puede simular varios escenarios de respuesta, incluidos retrasos, errores y diferentes códigos de estado HTTP.

En esta guía, aprenderás a:

- Utilizar Docker para iniciar un contenedor de WireMock.
- Utilizar datos simulados en el desarrollo local sin depender de una API externa.
- Utilizar una API real en producción para obtener datos meteorológicos en tiempo real de AccuWeather.

## Uso de WireMock con Docker

La [imagen oficial de Docker para WireMock](https://hub.docker.com/r/wiremock/wiremock) proporciona una forma conveniente de desplegar y gestionar instancias de WireMock. WireMock está disponible para varias arquitecturas de CPU, incluidas amd64, armv7 y armv8, lo que garantiza la compatibilidad con diferentes dispositivos y plataformas. Puedes obtener más información sobre WireMock independiente en el [sitio de documentación de WireMock](https://wiremock.org/docs/standalone/docker/).

### Requisitos previos

Se requieren los siguientes requisitos previos para seguir esta guía práctica:

- [Docker Desktop](https://www.docker.com/products/docker-desktop/)

### Inicio de WireMock

Inicia una demostración rápida de WireMock siguiendo estos pasos:

 1. Clona el [repositorio de GitHub](https://github.com/dockersamples/wiremock-node-docker) localmente.

    ```console
    $ git clone https://github.com/dockersamples/wiremock-node-docker
    ```

 2. Navega al directorio `wiremock-endpoint`

    ```console
    $ cd wiremock-node-docker/
    ```

    WireMock actúa como la API simulada con la que se comunicará tu backend para recuperar datos. Las respuestas simuladas de la API ya se han creado para ti en el directorio `mappings`.

 3. Inicia la pila de Compose ejecutando el siguiente comando en la raíz del directorio del proyecto clonado:

    ```console
    $ docker compose up -d
    ```

    Después de un momento, la aplicación estará activa y funcionando.

    ![Diagrama que muestra el contenedor de WireMock ejecutándose en Docker Desktop](/guides/images/wiremock-using-docker.webp)

    Puedes revisar los logs seleccionando el contenedor **wiremock-node-docker**:

    ![Diagrama que muestra los logs del contenedor de WireMock ejecutándose en Docker Desktop](/guides/images/wiremock-logs-docker-desktop.webp)

 4. Prueba la API simulada.

    ```console
    $ curl http://localhost:8080/api/v1/getWeather\?city\=Bengaluru
    ```

    Devolverá la siguiente respuesta predefinida con datos simulados:

    ```plaintext
    {"city":"Bengaluru","temperature":27.1,"conditions":"Mostly cloudy","forecasts":[{"date":"2024-09-02T07:00:00+05:30","temperature":83,"conditions":"Partly sunny w/ t-storms"},{"date":"2024-09-03T07:00:00+05:30","temperature":83,"conditions":"Thunderstorms"},{"date":"2024-09-04T07:00:00+05:30","temperature":83,"conditions":"Intermittent clouds"},{"date":"2024-09-05T07:00:00+05:30","temperature":82,"conditions":"Dreary"},{"date":"2024-09-06T07:00:00+05:30","temperature":82,"conditions":"Dreary"}]}
    ```

    Con WireMock, defines respuestas predefinidas utilizando archivos de mapeo. Para esta solicitud, los datos simulados se definen en el archivo JSON en `wiremock-endpoint/mappings/getWeather/getWeatherBengaluru.json`.

    Para obtener más información sobre la simulación de respuestas predefinidas, consulta la [documentación de WireMock](https://wiremock.org/docs/stubbing/).

## Uso de WireMock en desarrollo

Ahora que has probado WireMock, vamos a utilizarlo en el desarrollo y las pruebas. En este ejemplo, utilizarás una aplicación de ejemplo que tiene un backend de Node.js. Esta pila de aplicaciones tiene la siguiente configuración:

  - Entorno de desarrollo local: El contexto en el que se ejecutan el backend de Node.js y WireMock.
  - Backend de Node.js: Representa la aplicación de backend que gestiona las solicitudes HTTP.
  - API externa de AccuWeather: La API real de la que se obtienen los datos meteorológicos en tiempo real.
  - WireMock: El servidor simulado que imita las respuestas de la API durante las pruebas. Se ejecuta como un contenedor Docker.

  ![Diagrama que muestra la arquitectura de WireMock en desarrollo](/guides/images/wiremock-arch.webp)

  - En desarrollo, el backend de Node.js envía una solicitud a WireMock en lugar de a la API real de AccuWeather.
  - En producción, se conecta directamente a la API real de AccuWeather para obtener datos reales.

## Usar datos simulados en el desarrollo local

Vamos a configurar una aplicación de Node para enviar solicitudes al contenedor de WireMock en lugar de a la API real de AccuWeather.

### Requisito previo

- Instala [Node.js y npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
- Asegúrate de que el contenedor de WireMock esté activo y funcionando (consulta [Inicio de Wiremock](#inicio-de-wiremock))

Sigue los pasos para configurar una aplicación de Node no contenedorizada:

1. Navega al directorio `accuweather-api`

   Asegúrate de estar en el directorio donde se encuentra tu archivo `package.json`.

2. Establece la variable de entorno.

   Abre el archivo `.env` ubicado en el directorio `accuweather-api/`. Elimina las entradas anteriores y asegúrate de que solo contenga la siguiente línea.

   ```plaintext
   API_ENDPOINT_BASE=http://localhost:8080
   ```

   Esto le indicará a tu aplicación de Node.js que use el servidor de WireMock para las llamadas a la API.

3. Examina el punto de entrada de la aplicación

   - El archivo principal de la aplicación es `index.js`, ubicado en el directorio `accuweather-api/src/api`.
   - Este archivo inicia el módulo `getWeather.js`, que es esencial para tu aplicación de Node.js. Utiliza el paquete `dotenv` para cargar las variables de entorno desde el archivo `.env`.
   - Según el valor de `API_ENDPOINT_BASE`, la aplicación enruta las solicitudes al servidor de WireMock (`http://localhost:8080`) o a la API de AccuWeather. En esta configuración, utiliza el servidor de WireMock.
   - El código garantiza que `ACCUWEATHER_API_KEY` sea necesario solo si la aplicación no está utilizando WireMock, mejorando la eficiencia y evitando errores.

     ```javascript
     require("dotenv").config();

     const express = require("express");
     const axios = require("axios");

     const router = express.Router();
     const API_ENDPOINT_BASE = process.env.API_ENDPOINT_BASE;
     const API_KEY = process.env.ACCUWEATHER_API_KEY;

     console.log('API_ENDPOINT_BASE:', API_ENDPOINT_BASE);  // Log tras ser definido
     console.log('ACCUWEATHER_API_KEY is set:', !!API_KEY); // Logea un booleano en lugar de la clave real

     if (!API_ENDPOINT_BASE) {
       throw new Error("API_ENDPOINT_BASE is not defined in environment variables");
     }

     // Solo verifica la clave de la API si no se usa WireMock
     if (API_ENDPOINT_BASE !== 'http://localhost:8080' && !API_KEY) {
       throw new Error("ACCUWEATHER_API_KEY is not defined in environment variables");
     }
     // Función para obtener la clave de ubicación de la ciudad
     async function fetchLocationKey(townName) {
       const { data: locationData } = await
     axios.get(`${API_ENDPOINT_BASE}/locations/v1/cities/search`, {
         params: { q: townName, details: false, apikey: API_KEY },
       });
       return locationData[0]?.Key;
     }
     ```

4. Inicia el servidor de Node

   Antes de iniciar el servidor de Node, asegúrate de haber instalado los paquetes de Node enumerados en el archivo `package.json` ejecutando `npm install`.

   ```console
   $ npm install
   $ npm run start
   ```

   Deberías ver la siguiente salida:

    ```plaintext
    > express-api-starter@1.2.0 start
    > node src/index.js

    API_ENDPOINT_BASE: http://localhost:8080
    ..
    Listening: http://localhost:5001
    ```

   La salida indica que tu aplicación de Node se ha iniciado correctamente. Mantén abierta esta ventana de la terminal.

5. Prueba la API simulada

   Abre una nueva ventana de la terminal y ejecuta el siguiente comando para probar la API simulada:

   ```console
   $ curl "http://localhost:5001/api/v1/getWeather?city=Bengaluru"
   ```

   Deberías ver la siguiente salida:

   ```plaintext
   {"city":"Bengaluru","temperature":27.1,"conditions":"Mostly cloudy","forecasts":[{"date":"2024-09-02T07:00:00+05:30","temperature":83,"conditions":"Partly sunny w/ t-storms"},{"date":"2024-09-03T07:00:00+05:30","temperature":83,"conditions":"Thunderstorms"},{"date":"2024-09-04T07:00:00+05:30","temperature":83,"conditions":"Intermittent clouds"},{"date":"2024-09-05T07:00:00+05:30","temperature":82,"conditions":"Dreary"},{"date":"2024-09-06T07:00:00+05:30","temperature":82,"conditions":"Dreary"}]}%
   ```

   Esto indica que tu aplicación de Node.js ahora está enrutando con éxito las solicitudes al contenedor de WireMock y recibiendo las respuestas simuladas.

   Es posible que hayas notado que estás intentando usar `http://localhost:5001` como la URL en lugar del puerto `8080`. Esto se debe a que tu aplicación de Node.js se ejecuta en el puerto `5001` y está enrutando las solicitudes al contenedor de WireMock que escucha en el puerto `8080`.

   > [!TIP]
   > Antes de continuar con el siguiente paso, asegúrate de detener el servicio de la aplicación de Node.

## Usar una API real en producción para obtener datos meteorológicos en tiempo real de AccuWeather

Para mejorar tu aplicación de Node.js con datos meteorológicos en tiempo real, puedes integrar la API de AccuWeather directamente. Esta sección de la guía te guiará a través de los pasos necesarios para configurar una aplicación de Node.js no contenedorizada y obtener información meteorológica directamente de la API de AccuWeather.

1. Crear una clave de API de AccuWeather

   Regístrate para obtener una cuenta de desarrollador gratuita de AccuWeather en [https://developer.accuweather.com/](https://developer.accuweather.com/). Dentro de tu cuenta, crea una nueva aplicación seleccionando **MY APPS** en el menú de navegación superior para obtener tu clave de API única.

   ![Diagrama que muestra el panel de control de AccuWeather](/guides/wiremock/images/wiremock-accuweatherapi.webp)

   [AccuWeather API](https://developer.accuweather.com/) es una API web que proporciona datos y pronósticos meteorológicos en tiempo real. Los desarrolladores pueden utilizar esta API para integrar información meteorológica en sus aplicaciones, sitios web u otros proyectos.

2. Cambiar de directorio a `accuweather-api`

   ```console
   $ cd accuweather-api
   ```

3. Establece tu clave de API de AccuWeather utilizando el archivo `.env`:

   > [!TIP]
   > Para evitar conflictos, asegúrate de que se eliminen las variables de entorno existentes llamadas `API_ENDPOINT_BASE` o `ACCUWEATHER_API_KEY` antes de modificar el archivo `.env`.

   Ejecuta el siguiente comando en tu terminal:

   ```console
   $ unset API_ENDPOINT_BASE
   $ unset ACCUWEATHER_API_KEY
   ```

   Es hora de establecer las variables de entorno en el archivo `.env`:

   ```plaintext
   ACCUWEATHER_API_KEY=XXXXXX
   API_ENDPOINT_BASE=http://dataservice.accuweather.com
   ```

   Asegúrate de rellenar `ACCUWEATHER_API_KEY` con el valor correcto.

4. Instalar las dependencias

   Ejecuta el siguiente comando para instalar los paquetes requeridos:

   ```console
   $ npm install
   ```

   Esto instalará todos los paquetes enumerados en tu archivo `package.json`. Estos paquetes son esenciales para que el proyecto funcione correctamente.

   Si encuentras alguna advertencia relacionada con paquetes obsoletos, puedes ignorarla por el momento para esta demostración.

5. Suponiendo que no tienes un servidor de Node ejecutándose previamente en tu sistema, inicia el servidor de Node ejecutando el siguiente comando:

   ```console
   $ npm run start
   ```

   Deberías ver la siguiente salida:

   ```plaintext
   > express-api-starter@1.2.0 start
   > node src/index.js

   API_ENDPOINT_BASE: http://dataservice.accuweather.com
   ACCUWEATHER_API_KEY is set: true 
   Listening: http://localhost:5001
   ```

   Mantén abierta esta ventana de la terminal.

6. Ejecuta el comando curl para enviar una solicitud GET a la URL del servidor.

   En la nueva ventana de la terminal, introduce el siguiente comando:

   ```console
   $ curl "http://localhost:5000/api/v1/getWeather?city=Bengaluru"
   ```

   Al ejecutar el comando, le estás indicando a tu servidor local que te proporcione datos meteorológicos para una ciudad llamada `Bengaluru`. La solicitud se dirige específicamente al endpoint `/api/v1/getWeather` y estás proporcionando el parámetro de consulta `city=Bengaluru`. Once you execute the command, the server processes this request, fetches the data and returns it as a response, which `curl` will display in your terminal.

   Al obtener datos de la API externa de AccuWeather, estás interactuando con datos en tiempo real que reflejan las condiciones meteorológicas más recientes.

## Resumen

Esta guía te ha guiado a través de la configuración de WireMock utilizando Docker. Has aprendido a crear simulaciones (stubs) para imitar endpoints de API, lo que te permite desarrollar y probar tu aplicación sin depender de servicios externos. Al utilizar WireMock, puedes crear entornos de prueba fiables y consitentes, reproducir casos límite y acelerar tu flujo de trabajo de desarrollo.

