Intercept fetch() API requests and responses in JavaScript
For intercepting the fetch request and parameter we can go for below mentioned way. its resolved my issue.
const constantMock = window.fetch;
window.fetch = function() {
// Get the parameter in arguments
// Intercept the parameter here
return constantMock.apply(this, arguments)
}
Existing answers show the general structure for mocking fetch
in the browser but omit important details.
The accepted answer shows the general pattern for replacing the window.fetch
function with custom implementation that intercepts the call and forwards the arguments to fetch
. However, the pattern shown doesn't let the interception function do anything with the response (for example, read the status or body or inject a mock) so is only useful for logging request parameters. This is a pretty narrow use case.
This answer uses an async
function to let the interceptor await
on the fetch
promise and presumably work with the response (mocking, reading, etc) but (at the time of writing) has a superfluous closure and doesn't show how to read the response body non-destructively. It also contains a variable aliasing bug leading to a stack overflow.
This answer is the most complete so far but has some irrelevant noise in the callback and doesn't mention anything about cloning the response to enable the body to be collected by the interceptor. It doesn't illustrate how a mock could be returned.
Here's a minimal, complete example that rectifies these issues, showing how to handle parameter logging, reading the body without harming the original caller by cloning the response and (optionally) providing a mock response.
const {fetch: origFetch} = window;
window.fetch = async (...args) => {
console.log("fetch called with args:", args);
const response = await origFetch(...args);
/* work with the cloned response in a separate promise
chain -- could use the same chain with `await`. */
response
.clone()
.json()
.then(body => console.log("intercepted response:", body))
.catch(err => console.error(err))
;
/* the original response can be resolved unmodified: */
//return response;
/* or mock the response: */
return {
ok: true,
status: 200,
json: async () => ({
userId: 1,
id: 1,
title: "Mocked!!",
completed: false
})
};
};
// test it out with a typical fetch call
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then(response => response.json())
.then(json => console.log("original caller received:", json))
.catch(err => console.error(err))
;
For intercepting the response body you need to create a new Promise and resolve or reject current into "then" code. It solved for me and keep content for real app, e.g. React, etc.
const constantMock = window.fetch;
window.fetch = function() {
console.log(arguments);
return new Promise((resolve, reject) => {
constantMock
.apply(this, arguments)
.then((response) => {
if (response.url.indexOf("/me") > -1 &&
response.type != "cors") {
console.log(response);
// do something for specificconditions
}
resolve(response);
})
.catch((error) => {
reject(response);
})
});
}