mooc-course.com is learner-supported. When you buy through links on our site, we may earn an affiliate commission.

How to Test fetch JavaScript function?

Are you struggling to ensure your API calls work flawlessly? Worried about the reliability of your fetch functions? Seeking foolproof ways to test your JavaScript code? Look no further! Testing fetch functions is crucial for building robust, error-free web applications. In this guide, we’ll explore five powerful methods to test your fetch calls, empowering you to write more reliable and maintainable code.

How to Test fetch JavaScript function?

Before we dive into specific testing methods, let’s understand what fetch is and why testing it is important. The Fetch API provides a powerful and flexible way to make network requests in JavaScript. However, testing these asynchronous operations can be challenging. The basic syntax of a fetch call looks like this:

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

Now, let’s explore five methods to effectively test these fetch functions.

Read more: Find the minimum or maximum date using JavaScript

Method 1: Using Jest with Manual Mocks

This method uses Jest, a popular JavaScript testing framework, to create manual mocks for the fetch function.

Syntax:

// In your test file
global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({ data: 'mocked data' }),
  })
);

test('fetchData returns correct data', async () => {
  const data = await fetchData();
  expect(data).toEqual({ data: 'mocked data' });
});

Example:

// fetchData.js
export const fetchData = () => {
  return fetch('https://api.example.com/data')
    .then(response => response.json());
};

// fetchData.test.js
import { fetchData } from './fetchData';

global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({ data: 'mocked data' }),
  })
);

test('fetchData returns correct data', async () => {
  const data = await fetchData();
  expect(data).toEqual({ data: 'mocked data' });
  expect(global.fetch).toHaveBeenCalledWith('https://api.example.com/data');
});

Pros:

  • Full control over the mocked response
  • Integrates well with Jest’s assertion library

Cons:

  • Requires manual setup of the mock for each test
  • May not accurately represent all possible API responses

Method 2: Using fetch-mock Library

This method uses the fetch-mock library to intercept fetch calls and return predefined responses.

Syntax:

import fetchMock from 'fetch-mock';

fetchMock.get('https://api.example.com/data', { data: 'mocked data' });

test('fetchData returns correct data', async () => {
  const data = await fetchData();
  expect(data).toEqual({ data: 'mocked data' });
});

Example:

// fetchData.js
export const fetchData = () => {
  return fetch('https://api.example.com/data')
    .then(response => response.json());
};

// fetchData.test.js
import fetchMock from 'fetch-mock';
import { fetchData } from './fetchData';

describe('fetchData', () => {
  afterEach(() => {
    fetchMock.reset();
  });

  it('returns correct data', async () => {
    fetchMock.get('https://api.example.com/data', { data: 'mocked data' });
    const data = await fetchData();
    expect(data).toEqual({ data: 'mocked data' });
  });
});

Pros:

  • Easy to set up and use
  • Provides a wide range of mocking options

Cons:

  • Adds an extra dependency to your project
  • May require additional setup in complex testing environments

Method 3: Using sinon for Stubbing

This method uses the sinon library to create stubs for the fetch function.

Syntax:

import sinon from 'sinon';

const stub = sinon.stub(global, 'fetch');
stub.resolves({ json: () => Promise.resolve({ data: 'mocked data' }) });

test('fetchData returns correct data', async () => {
  const data = await fetchData();
  expect(data).to.deep.equal({ data: 'mocked data' });
});

Example:

// fetchData.js
export const fetchData = () => {
  return fetch('https://api.example.com/data')
    .then(response => response.json());
};

// fetchData.test.js
import sinon from 'sinon';
import { expect } from 'chai';
import { fetchData } from './fetchData';

describe('fetchData', () => {
  let stub;

  beforeEach(() => {
    stub = sinon.stub(global, 'fetch');
  });

  afterEach(() => {
    stub.restore();
  });

  it('returns correct data', async () => {
    stub.resolves({ json: () => Promise.resolve({ data: 'mocked data' }) });
    const data = await fetchData();
    expect(data).to.deep.equal({ data: 'mocked data' });
  });
});

Pros:

  • Powerful stubbing capabilities
  • Works well with various testing frameworks

Cons:

  • Requires additional setup and teardown in tests
  • May have a steeper learning curve for beginners

Method 4: Using node-fetch for Node.js Environments

This method uses the node-fetch library to polyfill fetch in Node.js environments for testing.

Syntax:

import fetch from 'node-fetch';
global.fetch = fetch;

jest.mock('node-fetch');

test('fetchData returns correct data', async () => {
  fetch.mockResolvedValue({
    json: () => Promise.resolve({ data: 'mocked data' }),
  });
  const data = await fetchData();
  expect(data).toEqual({ data: 'mocked data' });
});

Example:

// fetchData.js
export const fetchData = () => {
  return fetch('https://api.example.com/data')
    .then(response => response.json());
};

// fetchData.test.js
import fetch from 'node-fetch';
global.fetch = fetch;
jest.mock('node-fetch');

import { fetchData } from './fetchData';

describe('fetchData', () => {
  afterEach(() => {
    jest.resetAllMocks();
  });

  it('returns correct data', async () => {
    fetch.mockResolvedValue({
      json: () => Promise.resolve({ data: 'mocked data' }),
    });
    const data = await fetchData();
    expect(data).toEqual({ data: 'mocked data' });
    expect(fetch).toHaveBeenCalledWith('https://api.example.com/data');
  });
});

Pros:

  • Allows testing fetch in Node.js environments
  • Closely mimics browser fetch behavior

Cons:

  • Adds an extra dependency
  • May not be necessary if testing in a browser-like environment

Method 5: Using Modern Browser Testing Tools (e.g., Cypress)

This method uses modern browser testing tools like Cypress to test fetch calls in a real browser environment.

Syntax:

// In Cypress test file
cy.server();
cy.route('GET', 'https://api.example.com/data', { data: 'mocked data' }).as('getData');

cy.visit('/your-page');
cy.wait('@getData').its('response.body').should('deep.equal', { data: 'mocked data' });

Example:

// In your application code
function fetchData() {
  return fetch('https://api.example.com/data')
    .then(response => response.json());
}

// In Cypress test file
describe('Fetch Data Test', () => {
  it('fetches data correctly', () => {
    cy.server();
    cy.route('GET', 'https://api.example.com/data', { data: 'mocked data' }).as('getData');

    cy.visit('/your-page');
    cy.window().then((win) => {
      return win.fetchData();
    }).should('deep.equal', { data: 'mocked data' });

    cy.wait('@getData');
  });
});

Pros:

  • Tests in a real browser environment
  • Allows for end-to-end testing of fetch calls

Cons:

  • Requires setting up a separate testing framework
  • May be slower than unit tests

Which Method Should You Use?

The choice of method depends on your specific needs and project setup:

  1. Use Jest with manual mocks for simple unit testing in JavaScript projects.
  2. Choose fetch-mock for more comprehensive mocking capabilities.
  3. Opt for sinon if you need powerful stubbing features or are using a different testing framework.
  4. Use node-fetch for testing in Node.js environments.
  5. Consider Cypress or similar tools for end-to-end testing in real browser environments.

For most JavaScript projects, starting with Jest and manual mocks provides a good balance of simplicity and effectiveness. As your testing needs grow, you can explore more advanced options like fetch-mock or end-to-end testing with Cypress.

By mastering these techniques, you’ll be well-equipped to write robust tests for your fetch functions, ensuring your API calls work flawlessly across different scenarios. Remember, effective testing leads to more reliable and maintainable code. Happy testing!

 

Leave a Reply

Your email address will not be published. Required fields are marked *

Free Worldwide Courses

Learn online for free

Enroll in Multiple Courses

Learn whatever your want from anywhere, anytime

International Language

Courses offered in multiple languages & Subtitles

Verified Certificate

Claim your verified certificate