February 4, 2024

Homemade way for mocking api calls

During the development of an application we often need to simulate the response to an API call without having a real endpoint available.

When should I use mocks

  • When the API service is unavailable or unreliable
  • To emulate different response or errors
  • In development to work in parallel with backend team
  • In order to run tests in a controlled scenario
  • To work around permission issues

What should a mock look like

A mock has to be absolutely realistic and asynchronous. Realistic because you have to completely rely on it during development, asynchronous because it has to simulate the response time of a real API call.

There are several online services that provide dummy API responses, for example DummyJSON, awesome but nor realistic. And why not use just a local Json? It would contain realistic data. Sure, but the answer would be too fast and there could be unexpected synchronization bugs when the application will make real calls.

Homemade solution

There are a lot of services that meet this need, some for a fee, many are excellent, but in this post I want to suggest a simple and homemade solution. Like granny’s jam

The healthy solutions provided by Cary Grant’s grannies in “Arsenic and Old Lace”, Frank Capra 1944

This solution is written and tested in an Angular app, but it can be used in any other library or vanilla Javascript

  1. First of all we add a configuration file to turn the “mock mode” on or off. A simple mock: true will do its job. Ideally, this file should be related to the environment.

  2. Create all your mocks as simple json files in a folder. To avoid multiple import, it’s worth grouping them all into an index file

mock-folders.png

import data from './getData.json';
import dataError from './getDataError.json';
import post from './postDataError.json';
import postError from './postDataError.json';

export {
  data,
  dataError,
  post,
  postError
}

Index.ts

  1. If you are working in Angular you will surely have created a service for your API calls (if you haven’t, do so!). Let’s say that it’s named api.service.ts, here let’s import our mocks and all necessary dependencies.
import { Injectable } from '@angular/core';
import { configs } from '../../config'
import { of, delay } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { catchError } from 'rxjs';
// Import mocks
import * as mock from '../../mock/index'
  1. In our service, we also prepare the functions for the POST and GET calls.
/**
 * GET function wrapper.
 * Returns mock if configs.mock is true
 */
get(url: string, mock: any) {
    return (configs.mock ? of(mock) : this.http.get(url)).pipe(
        delay(configs.mock ? 1000 : 0),
        catchError((error: Error) => console.error(error))
    );
}

api.service.ts

/**
 * POST function wrapper.
 * Returns mock if configs.mock is true
 */
post(url: string, data: Data, mock: any) {
    return (configs.mock ? of(mock) : this.http.post(url, data)).pipe(
        delay(configs.mock ? 1000 : 0),
        catchError((error: Error) => console.error(error))
    );
}

api.service.ts

Here you can configure a different delay for fake calls to simulate a slower network, and you can create an interface for our mocks to have all the advantages of typescript.

  1. Now we can just use the previous wrappers in our API calls. Here are examples of GET and POST api calls
getData(page: number) {
  return this.get(`${this.baseUrl}/get?page=${page}`, mock.data)
}
postData(data: Data) {
  return this.post(`${this.baseUrl}/insert`, data, mock.post)
}

That is for today. And now, ladies and gentlemen, here is the greatest mock in the history of cinema. (the clip contains a spoiler, don’t watch it if you haven’t already seen the film.)

Marlene Dietrich in “Witness for the Prosecution”, Billy Wilder 1957

Irene Iaccio

Freelance web developer