How to Mock a Fetch request

Alejandro Toledo Freire
2 min readOct 14, 2021
jest logo.

When you create a test for your app making HTTP requests you are slowing your test down and also is not the best practice to do that. So, how do you avoid making HTTP requests in your tests?

On this page, I am going to teach you how to create a test for fetch requests but only if you are using fetch not any other method like Axios

This example is made on a React JS project and is going to show the easy way to handle those tests.

For this example, we are using the exchangerateapi.io to fetch the rate for a specific exchange.

This is the component from the ReactJS App.

async function convert(base, destination) {try {const result = await fetch(`https://api.exchangeratesapi.io/latest?base=${base}`);const data = await result.json();return data.rates[destination];} catch (error) {return error;}}export { convert };

One option when manually mocking a module is to create a folder named __mocks__ and place a file in it with the same name as the module you are mocking. In our case, we can do this, and that is because fetch is available globally. So instead we will override the global.fetch function with our own fake/mock version of it.

Keep in mind that if you want the JSON response, you are dealing with 2 promises.

// src/utils/currency.test.jsglobal.fetch = jest.fn(() =>Promise.resolve({json: () => Promise.resolve({ rates: { CAD: 1.42 } }),}));

With our mock in place, we can write code that tests the convert function.

// src/utils/currency.test.jsimport { convert } from "./currency";global.fetch = jest.fn(() =>Promise.resolve({json: () => Promise.resolve({ rates: { CAD: 1.43 } }),}));beforeEach(() => {fetch.mockClear();});it("finds exchange", async () => {const rate = await convert("USD", "CAD");expect(rate).toEqual(1.43);expect(fetch).toHaveBeenCalledTimes(1);});

The beforeEach to clear mocks isn't really required at this point because we only have a single test, but it's good practice to have so you get a fresh start between tests.

Manual Mocks With Failure

The test above tests the happy path, but if we want to verify that failure is handled by our function, we can override the mocked function to have it reject the promise. Calling fetch.mockImplementationOnce allows us to override the default mock behaviour just for this one test.

// src/utils/currency.test.jsit("returns null when exception", async () => {fetch.mockImplementationOnce(() => Promise.reject("API is down"));const rate = await convert("USD", "CAD");expect(rate).toEqual(null);expect(fetch).toHaveBeenCalledWith("https://api.exchangeratesapi.io/latest?base=USD");});

--

--