React ~ Testing ~ Mocking Functions - rohit120582sharma/Documentation GitHub Wiki

Mocking in Jest is about replacing dependencies with the Mock Function.

The Mock Function provides features to:

  • Capture calls
  • Set return values
  • Change the implementation or promise resolution

There are three main types of module and function mocking in Jest:

  • jest.spyOn: Spy or mock a function
  • jest.fn: Mock a function
  • jest.mock: Mock a module


jest.spyOn

Sometimes you only want to watch a method be called, but keep the original implementation:

import * as app from './app';
import * as math from './math';

test('calls math.add', () => {
    const addMock = jest.spyOn(math, 'add');

    // calls the original implementation
    expect(app.doAdd(1, 2)).toEqual(3);

    // and the spy stores the calls to add
    expect(addMock).toHaveBeenCalledWith(1, 2);
});

In other cases, you may want to mock a function (it's implementation), but then restore the original implementation later in the suite:

import * as app from './app';
import * as math from './math';

test('calls math.add', () => {
    const addMock = jest.spyOn(math, 'add');

    // Override the implementation
    addMock.mockImplementation(() => 'mock');
    expect(app.doAdd(1, 2)).toEqual('mock');

    // Restore the original implementation
    addMock.mockRestore();
    expect(app.doAdd(1, 2)).toEqual(3);
});


jest.fn

The most basic strategy for mocking is to reassign a function to the Mock Function. Then, anywhere the reassigned functions are used, the mock will be called instead of the original function:

One of the chances to use the Mock Function is that when your code supports dependency injection.

import * as app from './app';
import * as math from './math';

math.add = jest.fn();
math.subtract = jest.fn((a, b) => (a - b)); // with mock implementation

test('calls math.add', () => {
    app.doAdd(1, 2);
    expect(math.add).toHaveBeenCalledWith(1, 2);
});
test('calls math.subtract', () => {
    app.doSubtract(1, 2);
    expect(math.subtract).toHaveBeenCalledWith(1, 2);
});


jest.mock

A more common approach is to use jest.mock to automatically set all exports of a module to the Mock Function. The only disadvantage of this strategy is that it’s difficult to access the original implementation of the module.

import * as app from './app';
import * as math from './math';

// Set all module functions to jest.fn
jest.mock('./math.js', () => {
    const actualMath = require.requireActual('./math');
    return {
        ...actualMath,
        add: (a, b) => a + b,
        subtract: (a, b) => a - b
    };
});

beforeEach(() => {
    // Clear the mock data
    math.add.mockClear();
    math.subtract.mockClear();
});

test('should call math.add only onetime', () => {
    app.doAdd(1, 2);
    expect(math.add).toHaveBeenCalledTimes(1);
});
test('should call math.add with right arguments', () => {
    app.doAdd(1, 2);
    expect(math.add).toHaveBeenCalledWith(1, 2);
});

test('should call math.subtract only onetime', () => {
    app.doSubtract(1, 2);
    expect(math.add).toHaveBeenCalledTimes(1);
});
test('should calls math.subtract with right arguments', () => {
    app.doSubtract(1, 2);
    expect(math.subtract).toHaveBeenCalledWith(1, 2);
});


⚠️ **GitHub.com Fallback** ⚠️