How to make a mock API server in JavaScript
Tags: engineering
Published: 2022-10-24 08:10:36

---
title: How to make a mock API server in JavaScript
published: true
date: 2022-10-20 14:37:41 UTC
tags: Engineering
canonical_url: https://snyk.io/blog/how-to-mock-api-server-javascript/
---

Developing and testing a frontend feature can be difficult, especially when the backend it depends on is not ready. This dependency on a backend API often slows down the development process.

In scenarios like this, developing a mock API can save you a lot of time by allowing you to develop your feature independent of the backend, and make it easier to test and identify scenarios where your API might fail before it is ready.

In this article, you’ll learn more about mock API servers, the tools you can use to create mock APIs, how you can use them to speed up your development and testing, and how to set up a simple mock server.

## What is a mock API server?

A mock API server is a simulated API server that provides realistic responses to the requests it receives from a client. Typically, a mock API server is used to stand in for a backend server that’s still in development.

A mock API server mimics a real API by using placeholder data that contains realistic response values, but lacks many of the functional and non-functional characteristics of the original component, such as data persistence.

Mock API servers can be used in various scenarios, including the following:

- **Development:** Mock API servers temporarily remove the dependency between the frontend and backend teams, allowing them to work, develop, and test their components independently.
- **Testing:** Mock API servers facilitate testing, a crucial part of software development, by allowing the frontend team to test their features without waiting for the backend team to develop a fully functional API. Mock API servers also prevent the pollution of a real API with test data because all test calls are made to the mock API server, not the real one.
- **External components:** Mock API servers also help to mock out external dependencies when using tools like [Storybook](https://storybook.js.org/) to demonstrate frontend features.

## Best practices for mock APIs

When creating a mock API server, you should keep the following best practices in mind:

- A mock API should support the same schema and interfaces as the actual API. This makes sure the responses are more realistic.
- If your application requires external dependencies, your mock API should mock those dependencies, as well.
- A mock API should support request forwarding. This ensures that you can gradually switch from mock responses to real responses when the real API has been developed.
- A mock API should be able to simulate unexpected errors, slow performance, and invalid user inputs. This practice ensures that your applications can handle these scenarios properly.

## API Mocking Tools

There are many tools that can help create Mock API servers. Some of them include:

- [Mock Service Worker (MSW)](https://mswjs.io/): Mock Service Worker is an API mocking library which leverages the [Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). This API allows MSW to intercept actual requests and return mock responses by acting as a proxy server. Request interceptions happen on the network level, ensuring that your application does not know that the responses are coming from a mock API. 
- [Postman](https://www.postman.com/): Postman is a platform for building, using, testing, and documenting APIs. Postman also allows users to create mock API servers that return saved mock data. Postman returns the mock responses by matching the request configuration to the saved examples, and responds with the data that matches the configuration most closely. Postman offers an interactive GUI, which makes setting up a Postman mock server relatively easy.
- [Mirage JS](https://miragejs.com/): Mirage JS is an API mocking library that allows you to build and test a JavaScript application without depending on any backend services. Mirage JS makes it easy to create dynamic scenarios, making your mock API more realistic. Due to its ability to create dynamic scenarios and its in-memory database, Mirage JS provides the most flexibility for creating mock API servers. 

## Creating a mock API server with Mirage JS

This section will teach you how to create a simple mock API server with Mirage JS.

### Prerequisites

Before you begin, you need to have the following:

- [Node.js](https://nodejs.org/en/) v16 or higher installed on your system.
- The IDE of your choice.
- Basic knowledge of [React.js](https://reactjs.org/).

To follow along in your editor, begin by cloning the tutorial’s [GitHub repository](https://github.com/snyk-labs/todo-react-mock-api).

### Setting up your mock server

Run the following commands on your terminal to install the required dependencies and start your development server:

```
npm install
npm run start
```

You should see a spinning widget, and no functionality in the app. This is because your app is trying to fetch data from an API that isn’t ready. To speed up your development process, you will create a mock server.

![](https://snyk.io/wp-content/uploads/blog-mock-api-js-loading-1240x775.jpg)

In your `src` directory, create a file called `mock.js` and add the code block below:

```
//mock.js
import { createServer } from "miragejs";
 
const createMockServer = function () {
 let server = createServer();
 
 return server;
};
 
export default createMockServer;
```

In the code block above, you imported `createServer` from `miragejs`. This function starts up a Mirage server with a given configuration object. The configuration object can contain information such as various routes your server will handle, a mock in-memory database, and namespace.

The `createMockServer` function is responsible for creating and returning the instance.

### Creating an in-memory mock database

Next, you will create a simple mock database using Mirage’s data layer to store and return data.

Update your `mock.js` file to match the code block below:

```
//mock.js
import { createServer, Model } from "miragejs";
 
const createMockServer = function () {
 let server = createServer({
   models: {
     todos: Model
   },
 });
 
 return server;
};
 
export default createMockServer;
```

In the revised code block, you’re also importing `Model`, the base definition for [Mirage models](https://miragejs.com/docs/main-concepts/models/), from `miragejs`. 

Then you passed `createServer` a configuration object as an argument. Inside the configuration object, the `models` property is set to object, and inside the object of the `models` property, `todos` is set to `model`. This will tell Mirage to create an empty `todos` collection in its in-memory database.

### Seeding an in-memory database

Next, you’ll manually add some data to the in-memory database using the `seeds` hook. The `seeds` hook allows you to populate Mirage with some initial data so your mock API will have data to render when the application starts up for the first time.

To seed your database with some initial data, add the following code block under the `models` property in your `createServer` configuration object:

```
    //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,
    });
  },
```

In the code block above, you added the `seeds` hook to your configuration object. The `seeds` hook takes an instance of the server as an argument.

Then you added some data to your in-memory database by calling the `create` method on the server instance. The `create` method takes in two arguments: the singularized name (e.g. “todos” becomes “todo”) of the collection you wish to save the data to, and the data you want to save.

### Defining mock route handlers

Next, you’ll need to define the routes handlers using the `routes` hook. The `routes` hook allows you to specify route handlers for each available path and HTTP request.

Add the following code block to your `createServer` configuration object directly under the `seeds` hook to add the route handlers for your API calls:

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

In the code block above, you used the `routes` hook to define a global namespace for all the route handlers (`api/todos`) so that you don’t have to repeat it in each route handler.

Then you defined a `GET` route handler with the `get` method, which takes in a path and a callback. In the callback, the app is given access to the `schema` argument, which is used to access your in-memory database, and the `request` argument, which provides access to the request body.

Finally, you returned all the `todo`s in your in-memory database by calling the `all` method on `schema.todos`. You can access the in-memory model by chaining its name to the `schema` argument. The `all` method returns a `Collection` object with two properties, `modelName` and `models`.

The `modelName` property is the name of your model, and the `models` property is an array containing your seeded data.

Define the `POST` route handler by adding the following code into your `routes` hook:

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

In the callback function above, you get and parse the request body from the request object. Then you set the completed property to `false`, because by default, new tasks should not be complete. Mirage automatically assigns a unique `id` to every new todo by incrementing the `id` of the last todo that was initially seeded in the in-memory database. Finally, you used the `create“ method to add the new todo to the database.

Next, define the `PATCH` route handler by adding the following code into your `routes` hook:

```
   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);
   });
```

In the callback function above, you retrieve and parse the request body from the request object. Then, you destructure the `id` property from the `params` object attached to the request body. Using the `find` method, you query your in-memory database for a todo with a matching `id`. Finally, using the `update` method, you update the todo.

Define the `DELETE` route handler by adding the following code into your `routes` hook:

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

In this function, you destructured the `id` property from the `params` object attached to the request body. Then, using the `find` method, you queried your in-memory database for a todo with a matching `id`, and called the `destroy` method to remove it from your in-memory database.

Your completed mock server should look like this:

```
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;
```

Finally, import the `createMockServer` function into your `App.js` file, and start up your mock server by calling the `createMockServer` function in your `App.js` file.

For example:

```
//app.js
import createMockServer from "./mock";
 
createMockServer();
```

If you open your React application, you should see the to-do app rendering the seeded data from your mock API.

![](https://snyk.io/wp-content/uploads/blog-mock-api-js-app-1240x775.jpg)

You can now test your to-do app as you would with a real backend API.

## Wrapping up on mock API servers

This article taught you about mock API servers, their relevance, best practices for creating them, and tools that can help you make them. You’ve also learned how to create a simple mock API server using [Mirage JS](https://miragejs.com/).

Incorporating mock API servers in your development process will speed up your development and allow you to work independently, leading to a better workflow.