Mock APIs: Different Techniques for React and Angular

Shashikala Parakramasinghe
Image by PIRO4D from Pixabay

In web development, specialization improves productivity. In line with this, we can find developers who specialize in frontend or backend. However, splitting work and combining them to deliver functionality isn’t that easy when it comes to development. But the good news is, there are proven techniques that work in these circumstances.

To improve productivity, frontend developers can start their work by hardcoding values or mocking the backend API.

Mocking the backend is especially useful when delivering or sharing components as independent building blocks, using Bit (Github). As mentioned before, you don’t want to deliver front-end features without testing them first, but at the same time, you don’t want to be coupled to other developers or teams.

Components shared on Bit.dev as independent building blocks

This article will show how you can begin frontend development (and even deliver it independently) by mocking the backend.

Here is a list of topics I’m going to direct your focus towards.

  • Why Mock APIs?
  • What should be mocked? — A list of common modules suitable for mocking
  • JavaScript Libraries Available for Mocking
  • Mock React/Angular apps with JSON server
  • Angular CRUD backendless application with interceptors
  • React CRUD backendless application with Axios mock adapter
  • React CRUD backendless application with JSON server and Mirage JS

All the examples explained in this article have the same logic with the same components and one HTTP service for calling CRUD endpoints. The only difference between each example application would be the way of mocking.You can find the links to full source code alongside the examples.

Let’s start our discussion with “Why should we use Mock API.” To begin with, have a look at the following benefits of Mock APIs.

  • Frontend developers and backend developers can work in parallel, hence fast development.
  • UI/UX developers can start only the required backend mock APIs
  • The frontend can act as a standalone application during development without any backend API dependencies.
  • Enable offline development
  • Easy to demo
  • The mock API can easily be replaced with the Real API once it’s ready.

Now that you have understood API Mocking’s benefits let’s find out some common modules and operations suitable for mocking.

  • CRUD Operations — Create, Read, Update, and Delete operations in the application’s main user flows.
  • Authentication and Authorization Flow
  • Pagination
  • Search/Sort
  • Error Handling — e.g., Timeouts, delays, validations, etc.
  • File Download

So how do you get started on mocking our APIs? You can start by choosing a suitable library. Here is a list of popular javascript libraries for mocking.

Apart from these libraries, you can also use Http Interceptors for mocking API calls.

JSON server is one of the easiest and fastest ways of adding a mock REST API with a minimum configuration.

It offers basic validations like 404 if an entity is not found, 400 if the id already exists when trying to create a new entity. You can also check the network with browser dev tools to check the requests and responses.

The following are the steps to configure JSON Server.

Install JSON server globally

npm install -g json-server

Add a JSON file with mock data.

{
"countries": [
{"id":"1","name": "Finland", "capital": "Helsinki"},
{"id":"2","name": "Norway", "capital": "Oslo"},
{"id":"3","name": "Japan", "capital": "Tokyo"},
{"id":"4","name": "Germany", "capital": "Berlin"},
{"id":"5","name": "Russia", "capital": "Moscow"},
{"id":"6","name": "Kenya", "capital": "Nairobi"},
{"id":"7","name": "Sweden", "capital": "Stockholm"}
]
}

Start the JSON server

json-server --watch ./src/assets/mock-data/countries.json --port 8000

or add the following under the “scripts” section in the “package.json” file

"server": "json-server --watch ./src/assets/mock-data/countries.json --port 8000"

and execute the following command to run the server.

npm run server

One of the main drawbacks of the JSON server is Less flexibility.

For example, non-crud endpoints, different pagination parameters, different query parameters cannot be configured.

And also, the JSON server modifies the data permanently. If someone deletes all the data accidentally, they might have to set up test data again.

Find more about the JSON server at https://www.npmjs.com/package/json-server

Example — Angular CRUD App with JSON Server

Now, have a look at the following example where I have used JSON Server to mock CRUD operations of an Angular app.

Http Service

import {Country} from '../model/country';@Injectable({providedIn: 'root'})
export class CountryService {
private baseUrl = 'http://localhost:8000/countries';
constructor(private http: HttpClient) {}getAll(): Observable<Country[]> {
return this.http.get<any>(this.baseUrl);
}
get(id: string): Observable<Country> {
return this.http.get<any>(this.baseUrl + '/' + id);
}
create(country: Country) {
return this.http.post<any>(this.baseUrl, country);
}
update(id: string, country: Country): Observable<Country> {
return this.http.put<any>(this.baseUrl + '/' + id, country);
}
delete(id: string) {
return this.http.delete<any>(this.baseUrl + '/' + id);
}
}

Find Source code at https://github.com/spiyushani/angular-crud-with-json-server

Example — React CRUD App with JSON Server

Here is the same example used in a React application.

Http Service

import http from "../http-common";export const getAllCountries = () => {
return http.get("/countries");
};
export const getCountry = (id) => {
return http.get(`/countries/${id}`);
};
export const createCountry = (data) => {
return http.post("/countries", data);
};
export const updateCountry = (id, data) => {
return http.put(`/countries/${id}`, data);
};
export const removeCountry = (id) => {
return http.delete(`/countries/${id}`);
};

http-common.js class for creating an Axios instance

import axios from "axios";export default axios.create({
baseURL: "http://localhost:8000",
headers: {
"Content-type": "application/json"
}
});

Find full source code at https://github.com/spiyushani/react-crud-with-json-server

HTTP interceptors offer more flexibility than the JSON server and eliminate the necessity of running a server separately. However, HTTP requests will NOT be visible in the network tab in the browser dev tools if you use HTTP interceptors.

You can configure an HTTP interceptor to intercept the requests and return responses. Give your attention to the following configurations.

http-mock-api.interceptor.ts file

import {selectHandler} from './mock.config';@Injectable()
export class HttpMockApiInterceptor implements HttpInterceptor {
constructor() {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const mockEndpointHandler = selectHandler(request);
return mockEndpointHandler ? mockEndpointHandler(request) : next.handle(request);
}
}

Configure the interceptor in module.ts file

providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: HttpMockApiInterceptor,
multi: true
}
]

mock.config.ts file

import * as data from '../../assets/mock-data/countries.json';
import {Country} from '../model/country';
let countries: any[] = (data as any).default;const getCountries = (request: HttpRequest<any>) => {
return of(new HttpResponse({
status: 200, body: countries
}));
};
const getCountry = (request: HttpRequest<any>) => {
const id = extractIdPathParamFromUrl(request);
const country = countries.find(c => c.id === id);
return of(new HttpResponse({
status: 200, body: country
}));
};
const extractIdPathParamFromUrl = (request: HttpRequest<any>) => {
const requestUrl = new URL(request.url);
return requestUrl.pathname.split('/').pop();
};
export const selectHandler = (request: HttpRequest<any>) => {
const requestUrl = new URL(request.url);
const getOneRegexp: RegExp = new RegExp(`/countries/[0-9a-zA-Z]+`);
switch (request.method) {
case 'GET':
const pathname = requestUrl.pathname;
if (pathname === '/countries') {
return getCountries;
} else if (getOneRegexp.test(pathname)) {
return getCountry;
} else {
return null;
}
default:
return null;
}
};

Find full source code at https://github.com/spiyushani/angular-crud-with-mock-backend. Step by step guide can be found at https://dev.to/sanidz/angular-http-mock-interceptor-for-mocked-backend-1h5g

You can use Axios mock adapter to intercept Http calls in React applications using Axios as an Http client. However, Axios mock adapter only supports Axios.

Here is how you’d configure the Axios Mock Adapter

Install axios-mock-adapter

npm install axios-mock-adapter --save-dev

The following code snippet shows how to intercept HTTP requests.

mock.config.js

import data from '../assets/mock-data/countries.json'
import MockAdapter from "axios-mock-adapter";
let countriesList = data.countries;export const isMockEnabled = () => {
return process.env.REACT_APP_MOCK_ENABLED === 'true'
};
export const initializeAxiosMockAdapter = (instance) => {
const mock = new MockAdapter(instance);
mock.onGet("/countries").reply(() => getCountries());
mock.onGet(//countries/d+/).reply(config => getCountry(config));
};
export const getCountries = () => {
return [200, countriesList]
};
export const getCountry = (config) => {
const id = extractIdPathParamFromUrl(config);
const country = countriesList.find(c => c.id === id);
return [200, country];
};
const extractIdPathParamFromUrl = (config) => {
return config.url.split('/').pop();
};

Find full source code at https://github.com/spiyushani/react-crud-with-mock-backend. Find more about aixos-mock-adapter at https://www.npmjs.com/package/axios-mock-adapter

Mirage offers mocking facilities for a rest API with more elegant features than other libraries. You’d use Mirage on top of the JSON server to simulate some error scenarios.

Install Mirage JS

npm install --save-dev miragejs

mock-server.js

import {Response, Server} from "miragejs"// Create a new server instance - Intercepts the requests
if (process.env.NODE_ENV === "development") {
const server = new Server({
urlPrefix: "http://localhost:8000/",
namespace: "",
routes() {
this.get("/countries/:id", (schema, request) => {
let {id} = request.params;
switch (id) {
case "1":
return new Response(404, {"Content-Type": "application/json"}, {error: 'Country not found'});
}
});
},
});
server.passthrough();
}

Import mock-server in “index.js”

import "./mock-server";ReactDOM.render(
<App/>,
document.getElementById('root')
);

Mirage JS can act as a full-fledged mock server by injecting the data without using the JSON server. It also reloads mock data on browser refresh, unlike the JSON server. I have used both of them for simplicity and reducing some boilerplate code.

Find full source code at https://github.com/spiyushani/react-crud-app-with-json-server-miragejs. Find more about Mirage JS at https://miragejs.com/

If you only need to mock simple CRUD endpoints with basic validations, you may use the JSON server. If you want a more flexible and customizable solution, choose HTTP interceptors or other libraries. You can combine the JSON server with other interceptor solutions like Mirage JS with the least configuration to increase the flexibility.

I hope these examples will help you choose a suitable mock API method for your frontend applications.

Thanks for reading, and if you have any questions, let me know in the comment box below. 😊

Author: admin

Leave a Reply

Your email address will not be published.