Skip to main content

Cómo crear un servidor de API simulado en JavaScript

Escrito por

David Ekete

feature mock api js

20 de octubre de 2022

0 minutos de lectura

Desarrollar y probar una funcionalidad de frontend puede ser difícil, especialmente cuando el backend del que depende aún no está listo. Esta dependencia de una API de backend suele ralentizar el proceso de desarrollo.

En situaciones como esta, desarrollar una API simulada puede ahorrarte mucho tiempo, ya que te permite desarrollar tu funcionalidad sin depender del backend y facilita probar e identificar los casos en los que tu API podría fallar antes de que esté lista.

En este artículo, aprenderás sobre los servidores de API simulados, las herramientas que puedes usar para crearlos, cómo pueden acelerar el desarrollo y las pruebas, y cómo configurar un servidor simulado sencillo.

¿Qué es un servidor de API simulado?

Un servidor de API simulado es un servidor de API emulado que proporciona respuestas realistas a las solicitudes que recibe de un cliente. Por lo general, se usa para sustituir un servidor de backend que aún está en desarrollo.

Un servidor de API simulado imita una API real mediante datos de ejemplo con valores de respuesta realistas, pero carece de muchas de las características funcionales y no funcionales del componente original, como la persistencia de datos.

Los servidores de API simulados pueden usarse en diversas situaciones, como las siguientes:

  • Desarrollo: Los servidores de API simulados eliminan temporalmente la dependencia entre los equipos de frontend y backend, lo que les permite trabajar, desarrollar y probar sus componentes de forma independiente.

  • Pruebas: Los servidores de API simulados facilitan las pruebas, una parte esencial del desarrollo de software, porque permiten que el equipo de frontend pruebe sus funcionalidades sin esperar a que el equipo de backend desarrolle una API totalmente funcional. Además, evitan contaminar una API real con datos de prueba, ya que todas las llamadas de prueba se hacen al servidor de API simulado y no al real.

  • Componentes externos: Los servidores de API simulados también permiten emular dependencias externas al usar herramientas como Storybook para mostrar funcionalidades de frontend.

Prácticas recomendadas para las API simuladas

Al crear un servidor de API simulado, ten en cuenta las siguientes prácticas recomendadas:

  • Una API simulada debe admitir el mismo esquema y las mismas interfaces que la API real. Así, las respuestas serán más realistas.

  • Si tu aplicación requiere dependencias externas, tu API simulada también debe emularlas.

  • Una API simulada debe admitir el reenvío de solicitudes. Así, podrás pasar gradualmente de las respuestas simuladas a las reales cuando la API real esté lista.

  • Una API simulada debe poder simular errores inesperados, un rendimiento lento y entradas de usuario no válidas. De este modo, tus aplicaciones podrán manejar estas situaciones correctamente.

Herramientas para simular API

Hay muchas herramientas que pueden ayudarte a crear servidores de API simulados. Algunas son:

  • Mock Service Worker (MSW): Mock Service Worker es una biblioteca para simular API que aprovecha la API Service Worker. Esta API permite que MSW intercepte solicitudes reales y devuelva respuestas simuladas al actuar como servidor proxy. Las intercepciones de solicitudes ocurren a nivel de red, por lo que tu aplicación no sabe que las respuestas provienen de una API simulada.

  • Postman: Postman es una plataforma para crear, usar, probar y documentar API. También permite crear servidores de API simulados que devuelven datos simulados guardados. Postman devuelve las respuestas simuladas al comparar la configuración de la solicitud con los ejemplos guardados, y responde con los datos que más se ajustan a esa configuración. Postman ofrece una interfaz gráfica interactiva que facilita bastante la configuración de un servidor simulado.

  • Mirage JS: Mirage JS es una biblioteca para simular API que te permite crear y probar una aplicación JavaScript sin depender de servicios de backend. Facilita la creación de escenarios dinámicos, lo que hace que tu API simulada sea más realista. Gracias a la posibilidad de crear escenarios dinámicos y a su base de datos en memoria, Mirage JS ofrece la mayor flexibilidad para crear servidores de API simulados.

Cómo crear un servidor de API simulado con Mirage JS

En esta sección aprenderás a crear un servidor de API simulado sencillo con Mirage JS.

Requisitos previos

Antes de empezar, necesitas lo siguiente:

  • Tener instalada en tu sistema la versión 16 o posterior de Node.js.

  • El IDE que prefieras.

  • Conocimientos básicos de React.js.

Para seguir el tutorial en tu editor, empieza por clonar el repositorio de GitHub del tutorial.

Configurar tu servidor simulado

Ejecuta los siguientes comandos en la terminal para instalar las dependencias necesarias e iniciar el servidor de desarrollo:

npm install
npm run start

Deberías ver un componente animado y ninguna funcionalidad en la aplicación. Esto se debe a que la aplicación intenta obtener datos de una API que aún no está lista. Para acelerar el proceso de desarrollo, crearás un servidor simulado.

Pantalla de carga de una aplicación React con un indicador circular azul sobre un fondo verde azulado

En el directorio src, crea un archivo llamado mock.js y agrega el siguiente bloque de código:

//mock.js
import { createServer } from "miragejs";

const createMockServer = function () {
 let server = createServer();

 return server;
};

export default createMockServer;

En el bloque de código anterior, importaste createServer desde miragejs. Esta función inicia un servidor de Mirage con un objeto de configuración determinado. El objeto de configuración puede incluir información como las distintas rutas que manejará el servidor, una base de datos simulada en memoria y un espacio de nombres.

La función createMockServer se encarga de crear y devolver la instancia.

Crear una base de datos simulada en memoria

A continuación, crearás una base de datos simulada sencilla con la capa de datos de Mirage para almacenar y devolver datos.

Actualiza el archivo mock.js para que coincida con el siguiente bloque de código:

//mock.js
import { createServer, Model } from "miragejs";

const createMockServer = function () {
 let server = createServer({
   models: {
     todos: Model
   },
 });

 return server;
};

export default createMockServer;

En el bloque de código actualizado, también importas Model, la definición base de los modelos de Mirage, desde miragejs.

Luego, pasaste un objeto de configuración como argumento a createServer. Dentro del objeto de configuración, la propiedad models se establece en un objeto y, dentro del objeto de la propiedad models, todos se establece en model. Esto le indica a Mirage que cree una colección todos vacía en su base de datos en memoria.

Cargar datos iniciales en una base de datos en memoria

A continuación, agregarás algunos datos manualmente a la base de datos en memoria usando el hook seeds. El hook seeds te permite cargar datos iniciales en Mirage para que la API simulada tenga datos que mostrar cuando la aplicación se inicie por primera vez.

Para cargar algunos datos iniciales en la base de datos, agrega el siguiente bloque de código debajo de la propiedad models en el objeto de configuración de createServer:

    //mock.js
   seeds(server) {
    server.create("todo", {
      id: 1,
      title: "Reach out to a friend",
      completed: true,
    });

    server.create("todo", {
      id: 2,
      title: "Make breakfast",
      completed: true,
    });

    server.create("todo", {
      id: 3,
      title: "Text John Doe",
      completed: false,
    });
  },

En el bloque de código anterior, agregaste el hook seeds al objeto de configuración. El hook seeds recibe una instancia del servidor como argumento.

Luego, agregaste datos a la base de datos en memoria llamando al método create en la instancia del servidor. El método create recibe dos argumentos: el nombre singularizado (por ejemplo, "todos" se convierte en "todo") de la colección donde quieres guardar los datos y los datos que quieres guardar.

Definir los controladores de rutas simuladas

A continuación, tendrás que definir los controladores de rutas usando el hook routes. El hook routes te permite especificar controladores para cada ruta disponible y solicitud HTTP.

Agrega el siguiente bloque de código al objeto de configuración de createServer, justo debajo del hook seeds, para agregar los controladores de rutas de las llamadas a la API:

routes() {
    this.namespace = "api/todos";

    this.get("/", (schema, request) => {
      return schema.todos.all().models
    });
  },

En el bloque de código anterior, usaste el hook routes para definir un espacio de nombres global para todos los controladores de rutas (api/todos) y así no tener que repetirlo en cada controlador.

Luego, definiste un controlador de ruta GET con el método get, que recibe una ruta y una función de devolución de llamada. En esa función, la aplicación tiene acceso al argumento schema, que se usa para acceder a la base de datos en memoria, y al argumento request, que permite acceder al cuerpo de la solicitud.

Por último, devolviste todos los elementos todo de la base de datos en memoria llamando al método all en schema.todos. Puedes acceder al modelo en memoria encadenando su nombre al argumento schema. El método all devuelve un objeto Collection con dos propiedades: modelName y models.

La propiedad modelName es el nombre de tu modelo y la propiedad models es una matriz que contiene los datos cargados inicialmente.

Define el controlador de ruta POST agregando el siguiente código al hook routes:

  this.post("/new", (schema, request) => {
       let attrs = JSON.parse(request.requestBody);
       attrs.completed = false;

       return schema.todos.create(attrs);
   });

En la función de devolución de llamada anterior, obtienes y analizas el cuerpo de la solicitud a partir del objeto request. Luego, estableces la propiedad completed en false, porque, de forma predeterminada, las tareas nuevas no deben estar completadas. Mirage asigna automáticamente un id único a cada tarea nueva, incrementando el id de la última tarea cargada inicialmente en la base de datos en memoria. Por último, usaste el método `create`` para agregar la tarea nueva a la base de datos.

A continuación, define el controlador de ruta PATCH agregando el siguiente código al hook routes:

   this.patch("/:id", (schema, request) => {
       let newAttrs = JSON.parse(request.requestBody);
       let { id } = request.params;
       let todo = schema.todos.find(id);
       return todo.update(newAttrs);
   });

En la función de devolución de llamada anterior, recuperas y analizas el cuerpo de la solicitud a partir del objeto request. Luego, extraes la propiedad id del objeto params adjunto al cuerpo de la solicitud. Con el método find, consultas la base de datos en memoria para encontrar una tarea con un id coincidente. Por último, actualizas la tarea con el método update.

Define el controlador de ruta DELETE agregando el siguiente código al hook routes:

  this.delete("/:id", (schema, request) => {
       let { id } = request.params;
       return schema.todos.find(id).destroy();
   });

En esta función, extrajiste la propiedad id del objeto params adjunto al cuerpo de la solicitud. Luego, con el método find, buscaste en la base de datos en memoria una tarea con un id coincidente y llamaste al método destroy para eliminarla de la base de datos en memoria.

Tu servidor simulado completo debería verse así:

import { createServer, Model } from "miragejs";

const createMockServer = function () {
 let server = createServer({
   models: {
     todos: Model,
   },

   seeds(server) {
     server.create("todo", {
       id: 1,
       title: "Reach out to a friend",
       completed: true,
     });

     server.create("todo", {
       id: 2,
       title: "Make breakfast",
       completed: true,
     });

     server.create("todo", {
       id: 3,
       title: "Text John Doe",
       completed: false,
     });
   },

   routes() {
     this.namespace = "api/todos";

     this.get("/", (schema, request) => {
       return schema.todos.all().models;
     });

     this.post("/new", (schema, request) => {
       let attrs = JSON.parse(request.requestBody);
       attrs.completed = false;

       return schema.todos.create(attrs);
     });

     this.patch("/:id", (schema, request) => {
       let newAttrs = JSON.parse(request.requestBody);
       let id = request.params.id;
       let todo = schema.todos.find(id);
       return todo.update(newAttrs);
     });

     this.delete("/:id", (schema, request) => {
       let id = request.params.id;
       return schema.todos.find(id).destroy();
     });
   },
 });

 return server;
};

export default createMockServer;

Por último, importa la función createMockServer en el archivo App.js e inicia el servidor simulado llamando a la función createMockServer en el archivo App.js.

Por ejemplo:

//app.js
import createMockServer from "./mock";

createMockServer();

Si abres tu aplicación React, deberías ver la aplicación de tareas mostrando los datos iniciales de tu API simulada.

Aplicación de lista de tareas que muestra tareas completadas, una tarea sin marcar «Escribirle a John Doe» y un campo para agregar una nueva tarea

Ahora puedes probar tu aplicación de tareas como lo harías con una API de backend real.

Conclusión sobre los servidores de API simulados

En este artículo aprendiste qué son los servidores de API simulados, por qué son útiles, cuáles son las prácticas recomendadas para crearlos y qué herramientas pueden ayudarte. También aprendiste a crear un servidor de API simulado sencillo con Mirage JS.

Incorporar servidores de API simulados a tu proceso de desarrollo acelerará el trabajo y te permitirá trabajar de manera independiente, lo que mejorará tu flujo de trabajo.

Publicado en: