All Articles

Testing node-fetch with jest in TypeScript

Because I haven’t seen it anywhere else, and because it was a bit tricky to set up, here is an example of testing some code that uses the node-fetch library with TypeScript.

First install fetch-mock-jest, fetch-mock and its types package @types/fetch-mock.

Then, set up your test like follows:

import type { FetchMockStatic } from 'fetch-mock';
import fetch from 'node-fetch';
// We need this import to get the extra jest assertions
import 'fetch-mock-jest';

// Mock 'node-fetch' with 'fetch-mock-jest'. Note that using
// require here is important, because jest automatically hoists
// `jest.mock()` calls to the top of the file (before imports),
// so if we were to refer to an imported module, we would get a
// ReferenceError
jest.mock('node-fetch', () => require('fetch-mock-jest').sandbox());

// Cast node-fetch as fetchMock so we can access the `.mock*()` methods
const fetchMock = (fetch as unknown) as FetchMockStatic;

describe('code that uses fetch', () => {
  beforeEach(() => fetchMock.reset());

  it('should fetch a simple URL correctly', async () => {
    fetchMock.get('https://example.com', { value: 1234 });
    await fetch('https://example.com');
    expect(fetchMock).toHaveFetched({ url: 'https://example.com' });
  });

  it('should handle more complicated assertions', () => {
    fetchMock.post('https://example.com/submit', { status: 'ok' });

    const result = await fetch('https://example.com/submit', {
      method: 'post',
      body: JSON.stringify({
        type: 'create',
        details: {
          username: 'chris',
          passwordToken: 'abcde12345',
        },
      }),
      headers: { 'content-type', 'application/json' },
    });

    // Check we called the right URL, method and part of the body
    expect(fetchMock).toHaveFetched('https://example.com/submit', {
      matchPartialBody: true,
      method: 'post',
      body: { type: 'create' },
    })
  });
});