With web development constantly evolving, we’ve seen an increasing adaptation to client-server architecture in the ecosystem. While this architecture has many advantages, one of its most common challenges is the time frontend developers spend waiting for the backend team to implement new API endpoints or modify existing ones.
While most teams propose a full-stack development approach to solving this challenge, API mocking has proven to be the most efficient solution.
Mocking allows frontend developers to simulate the responses and behaviors of a live API, such as error handling, timeouts, and specific status codes in real time. Chrome DevTools Local Overrides make this even easier without complex integrations or writing code.
In this tutorial, we will explore how to use Chrome DevTools Local Overrides for API mocking. We’ll mock API response data in a production website without accessing the backend. The tutorial will also cover how to bypass Cross-Origin Resource Sharing (CORS) issues without modifying the server code.
Before moving forward with this tutorial, you should have:
Over the years, the JavaScript ecosystem has developed many libraries for mocking APIs on the browser and Node.js environments. This section will highlight the common tools and libraries for mocking APIs and the limitations of these libraries.
Mock Service Worker (MSW) is a popular API mocking library that supports both mocking in the browser and Node.js. It allows you to intercept requests and mock corresponding responses.
It supports mocking for RESTful, GraphQL, and WebSocket APIs.
Here is an HTTP request handler for mocking a GET
request with MSW:
import { http, HttpResponse } from 'msw' export const handlers = [ http.get('https://example.com/user', () => { return HttpResponse.json({ id: 'c7b3d8e0-5e0b-4b0f-8b3a-3b9f4b3d3b3d', firstName: 'John', lastName: 'Maverick', }) }), ]
The handler intercepts GET https://example.com/user
requests and then responds with mock JSON data.
Limitations of MSW include:
The Axios Mock Adapter is an API mocking library specifically designed for mocking response headers and data for API calls made with Axios. It works on Node.js and also in a browser.
Here is an HTTP request handler for mocking a GET
request with Axios Mock Adapter:
const axios = require("axios"); const AxiosMockAdapter = require("axios-mock-adapter"); const mock = new AxiosMockAdapter(axios); mock.onGet("/users").reply(200, { users: [{ id: 1, name: "John Smith" }], });
mock.onGet
intercepts any GET
request to the specified endpoint and then responds with mock JSON data. It also receives arguments such as status, data, and headers.
Limitations of Axios Mock Adapter include:
Mirage JS is my favorite API mocking library. It’s designed to replicate your entire production API server. It ships with an in-memory database and lets you build out fully dynamic features, with data-fetching and persistence logic. Mirage JS uses factories to quickly simulate various server states.
Since 2017, I have been developing critical customer-facing apps with Mirage JS without a backend; all I do is take user stories from our product manager and translate them into fully functional web apps. It is very handy, especially when working under tight deadlines to spin up MVPs efficiently.
Here is an HTTP request handler for mocking a GET
request with Mirage JS:
import { createServer } from "miragejs" createServer({ routes() { this.get("/api/users", () => [ { id: "1", name: "Luke" }, { id: "2", name: "Leia" }, { id: "3", name: "Anakin" }, ]) }, })
Limitations of Mirage JS include:
This section will cover a brief overview of the tools available in Chrome DevTools, especially for network inspection, debugging, and testing. We’ll also discuss how these tools allow you to inspect, modify, and intercept API calls in real-time.
Imagine you’re dealing with an issue in your production environment. Maybe there’s a typo in an API call, or you’re running into an unexpected CORS error but don’t have the privilege to make changes in production. That’s where the DevTools Local Overrides feature comes in handy! It lets you temporarily modify resources and experiment with different scenarios right from your browser, without modifying your site in production.
The Network tab in Chrome DevTools is a powerful tool for monitoring and debugging network activity in web applications. It provides a detailed view of all network requests made by a webpage.
Chrome DevTools Local Overrides provides the following benefits, discussed in further detail below:
This section will cover how to simulate different API responses directly from the browser without needing external mocking services.
Open DevTools in any production website of your choice, navigate to the Network panel, right-click a request you want to override, and choose Override content from the drop-down menu.
We intend to modify the scoreboard on the goal.com website:
Now, DevTools will prompt you to Select a folder in which to store the override files:
After selecting the folder, DevTools will prompt you to grant access rights to it. Click Allow to do so.
Now, local overrides are set up and enabled. DevTools should take you to the Sources panel to let you make changes to web content.
Now we can modify the scoreboard data and refresh the page to see the changes:
For situations where you are working on a data-driven frontend application and the backend API endpoints are not available, you can mock the API response directly in the browser. This is possible if you already know the data structure for the API response.
Here is a React app that fetches data from the JSONPlaceholder Rest API:
import React, { useEffect, useState } from 'react'; import axios from 'axios'; import './App.css'; const App = () => { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchUsers = async () => { try { const response = await axios.get('https://jsonplaceholder.typicode.com/footballers'); setUsers(response.data); setLoading(false); } catch (err) { setError('Failed to fetch data'); setLoading(false); } }; fetchUsers(); }, []); if (loading) return <p className="loading">Loading...</p>; if (error) return <p className="error">Error: {error}</p>; return ( <div className="container"> <h1 className="title">User List</h1> <ul className="userList"> {users.map((user) => ( <li key={user.id} className="userCard"> <p><strong>Name:</strong> {user.name}</p> <p><strong>Email:</strong> {user.email}</p> <p><strong>Phone:</strong> {user.phone}</p> <p><strong>Website:</strong> <a href={`https://${user.website}`} target="_blank" rel="noopener noreferrer">{user.website}</a></p> </li> ))} </ul> </div> ); }; export default App;
The JSONPlaceholder Rest API does not have the /footballers
endpoint that we called in our React app, so this will result in a 404 error. However, we can mock the response data for this endpoint in our React app while waiting for the JSONPlaceholder backend team to make this endpoint available.
Open Chrome DevTools, navigate to the Network tab and then reload the page. Notice the 404 error in the /footballers
endpoint. Right-click the /footballers
endpoint, and choose Override content from the drop-down menu:
You should see the following pane:
Now you can add the following mock data in the above pane:
[ { "id": 1, "name": "Leanne Graham", "username": "Bret", "email": "[email protected]", "address": { "street": "Kulas Light", "suite": "Apt. 556", "city": "Gwenborough", "zipcode": "92998-3874", "geo": { "lat": "-37.3159", "lng": "81.1496" } }, "phone": "1-770-736-8031 x56442", "website": "hildegard.org", "company": { "name": "Romaguera-Crona", "catchPhrase": "Multi-layered client-server neural-net", "bs": "harness real-time e-markets" } }, { "id": 2, "name": "Ervin Howell", "username": "Antonette", "email": "[email protected]", "address": { "street": "Victor Plains", "suite": "Suite 879", "city": "Wisokyburgh", "zipcode": "90566-7771", "geo": { "lat": "-43.9509", "lng": "-34.4618" } }, "phone": "010-692-6593 x09125", "website": "anastasia.net", "company": { "name": "Deckow-Crist", "catchPhrase": "Proactive didactic contingency", "bs": "synergize scalable supply-chains" } }, { "id": 3, "name": "Clementine Bauch", "username": "Samantha", "email": "[email protected]", "address": { "street": "Douglas Extension", "suite": "Suite 847", "city": "McKenziehaven", "zipcode": "59590-4157", "geo": { "lat": "-68.6102", "lng": "-47.0653" } }, "phone": "1-463-123-4447", "website": "ramiro.info", "company": { "name": "Romaguera-Jacobson", "catchPhrase": "Face to face bifurcated interface", "bs": "e-enable strategic applications" } }, { "id": 4, "name": "Patricia Lebsack", "username": "Karianne", "email": "[email protected]", "address": { "street": "Hoeger Mall", "suite": "Apt. 692", "city": "South Elvis", "zipcode": "53919-4257", "geo": { "lat": "29.4572", "lng": "-164.2990" } }, "phone": "493-170-9623 x156", "website": "kale.biz", "company": { "name": "Robel-Corkery", "catchPhrase": "Multi-tiered zero tolerance productivity", "bs": "transition cutting-edge web services" } } ]
Reload the page and you should have the mocked data rendered in your React app:
You can also override response headers, which is particularly useful for testing CORS issues or other security-related header changes.
For instance, if a page encounters a CORS error preventing data from loading, it often requires server-side adjustments. While waiting for the backend team to resolve the issue, you can temporarily modify the headers yourself to test and continue your development without delays:
Navigate to the Network tab then right-click the endpoint with the CORS issue, and choose Override headers from the drop-down menu:
Click Add header then add Access-Control-Allow-Origin
and set its value to *
:
Reload the page and the CORS error will be gone:
Chrome Local Override automatically persists mocked data and stores other overridden resources in your drive.
Navigate to the Sources tab, then click Overrides. Right-click the overridden file, choose Open in containing folder from the drop-down menu:
You can right-click to open the folder and edit the files using your favorite code editor. Even better, you can sync the folder to a shared location, making it easy to collaborate and share with your colleagues.
While Chrome DevTools allows you to mock APIs without writing any code, there are many scenarios where external API mocking libraries are a better choice:
External libraries like MSW and Mirage JS allow you to programmatically mock APIs in unit and integration tests. Chrome DevTools doesn’t support test automation.
Chrome DevTools is limited to Chromium-based browsers only while external libraries are browser-agnostic.
When working with CI/CD pipelines for test automation, external libraries are better choices as DevTools doesn’t support CI/CD workflows.
If you need to share your mock setups across teams, external libraries are preferable because it’s easy to share code via Git.
In this tutorial, we explored common API mocking libraries, their limitations, and how to use DevTools Local Overrides for API mocking in a production website without accessing the backend. We also covered how to bypass CORS issues without modifying the server code, and when to still use API mocking libraries.
If you’re prototyping UI designs without a backend or testing API fixes before they go live, you should consider trying out Chrome DevTools Local Override. You’ll be surprised at how much easier your tasks can be!
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowEnhance navigation in multi-page apps using the View Transition API, CSS, and JavaScript — no heavy frameworks needed.
Developers can take advantage of the latest release of .NET MAUI 9 to build better user experiences that more accurately react and respond to changes in their applications.
React Islands integrates React into legacy codebases, enabling modernization without requiring a complete rewrite.
Onlook bridges design and development, integrating design tools into IDEs for seamless collaboration and faster workflows.