Introduction part

In a project, it is common for methods in one module to call methods in another module. In unit tests, we might not care about the execution and results of an internally called method, just whether it was called correctly, and even specify the return value of that function. In this case, it is necessary to use Mock functions.

Jest objects have fn,mock, and spyOn methods. In actual project unit tests, jest.fn() is often used to test some callback functions. Jest. Mock () can mock methods in an entire module. When a module is 100% covered by a unit test, using jest. Mock () is necessary to save test time and redundancy. Jest. SpyOn () is often used when you need to test some method that must be executed in its entirety.

Jest.fn()

Jest.fn () is the easiest way to create Mock functions, and if the internal implementation of the function is not defined, jest.fn() returns undefined as the return value.

test('Test the jest. Fn () call'.() = > {
  let mockFn = jest.fn();
  let result = mockFn(1.2.3);

  // Assert that execution of mockFn returns undefined
  expect(result).toBeUndefined();
  // Assert mockFn is called
  expect(mockFn).toBeCalled();
  // Assert that mockFn is called once
  expect(mockFn).toBeCalledTimes(1);
  // Assert that mockFn passes in arguments 1, 2, 3
  expect(mockFn).toHaveBeenCalledWith(1.2.3);
})
Copy the code

The Mock function created by jest.fn() can also set return values, define internal implementations, or return Promise objects.

test('Test jest.fn() returns fixed value'.() = > {
  let mockFn = jest.fn().mockReturnValue('default');
  Assert that mockFn returns a value of default after execution
  expect(mockFn()).toBe('default');
})

test('Test the internal implementation of jest.fn()'.() = > {
  let mockFn = jest.fn((num1, num2) = > {
    return num1 * num2;
  })
  MockFn returns 100 after execution
  expect(mockFn(10.10)).toBe(100);
})

test('Test jest.fn() returns Promise'.async() = > {let mockFn = jest.fn().mockResolvedValue('default');
  let result = await mockFn();
  // assert mockFn returns default after execution with await keyword
  expect(result).toBe('default');
  // Assert that the mockFn call returns the Promise object ❌
  expect(Object.prototype.toString.call(mockFn())).toBe("[object Promise]");
  // This returns a String, and returns a Promise.
})
Copy the code

Let’s write some tested code in the SRC /fetch. Js file to understand the Mock function in action in a more businesslike way.

The code under test relies on axios, the common request library, and the JSONPlaceholder request interface. Please run NPM install AXIos –save to install the dependencies in the shell.

// fetch.js
const axios = require('axios');

async function fetchPostsList(callback) {
    return axios.get('https://jsonplaceholder.typicode.com/posts').then(res= > {
        returncallback(res.data); })}module.exports = fetchPostsList;
Copy the code

We’ve wrapped a fetchPostsList method in fetch. Js that requests the interface provided by JSONPlaceholder and returns the processed return value via the incoming callback function. If we want to test that the interface can be called properly, we just need to catch that the incoming callback function can be called properly. Here is the code for the tests in functions.test.js.

const fetch = require('.. /src/fetch');
test('fetchPostsList callback was called'.async () => {
    expect.assertions(1);
    let mockFn = jest.fn();
    await fetch(mockFn);

    // Assert mockFn is called
    expect(mockFn).toBeCalled();
})
Copy the code

.mockattribute

All mock functions have a special.mock attribute, which holds information about how the function was called and the return value when it was called.

test('test function forEach'.() = > {
    const mockCallback = jest.fn(x= > 88 + x);
    forEach([0.1], mockCallback);
    // The number of times the mock function was called
    expect(mockCallback.mock.calls.length).toBe(2);
    // The first argument to the function is 0
    expect(mockCallback.mock.calls[0] [0]).toBe(0);
    MockCallback is the second argument when the function is called the first time
    // expect(mockCallback.mock.calls[0][1]).toBe(1); ?????
    // The second time the function is called, the first argument is 1
    expect(mockCallback.mock.calls[1] [0]).toBe(1);
    // The return value of the first function call is 88
    expect(mockCallback.mock.results[0].value).toBe(88);
    The return value of the second function call is 89
    expect(mockCallback.mock.results[1].value).toBe(89);
})
Copy the code

Jest.mock()

Typically, you need to call an API, send an Ajax request, and get data from the background. However, when we do front-end test, we do not need to call the real interface, so we need to simulate the AXIos/FETCH module at this time, so that it can test whether our interface call is correct without calling API.

// events.js
const fetch = require('./fetch');

async function getPostList() {
    return fetch(data= > {
        console.log('fetchPostsLits be called'); })}module.exports = getPostList;
Copy the code

The test code is as follows:

const fetch = require('.. /src/fetch');
const event = require('.. /src/event');
jest.mock('.. /src/fetch.js');

test('fetchPostsList callback was called'.async () => {
    expect.assertions(1);
    let mockFn = jest.fn();
    await fetch(mockFn);

    expect(mockFn).toBeCalled();
})
// There will be an error
/* Error: expect(received).toHaveBeenCalled() Matcher error: received value must be a mock or spy function Received has value: undefined at Object.
      
        (/Users/giriawu/Documents/test_demo/getting-started-with-jest/__tests__/functions.test.js:15:21) at processTicksAndRejections (internal/process/task_queues.js:93:5) */
      
// How to solve it?
test('mock all fetch.js'.async () => {
    expect.assertions(2);
    await event();
    expect(fetch()).toHaveBeenCalled()
    expect(fetch()).toHaveBeenCalledTimes(1);
})
Copy the code

Mock (‘axios’) was used to mock the entire fetch. Js module in the test code. If you comment out this line of code, an error will occur when the test script is executed

Note: In Jest, if you want to capture a function call, the function must be mock or spy!

Jest.spyOn()

The jest.spyon () method also creates a mock function, but the mock function not only captures the function invocation, but also executes the spy function normally. In fact, jest.spyon () is the syntactic sugar of jest.fn(), which creates a mock function with the same internal code as the spy function.

The jest.spyon () method creates a mock function and executes the spy function normally. Jest.spyon () is the syntactic sugar of jest.fn(), which creates a mock function with the same internal code as the spy function.

import events from '.. /src/events';
import fetch from '.. /src/fetch';
 
test('Use jest.spyon () to monitor that fetch. FetchPostsList is called properly'.async() => {
  expect.assertions(2);
  / /???
  const spyFn = jest.spyOn(fetch, 'fetchPostsList');
  await events.getPostList();
  expect(spyFn).toHaveBeenCalled();
  expect(spyFn).toHaveBeenCalledTimes(1);
})
Copy the code

TIPS: If you want to capture a function call in Jest, the function must be mock or spyOn!

Timer Mock

Jest simulates a timer to allow autonomic control of time passing. Analog timer running can facilitate testing, such as getting results directly without waiting for a long delay.

The main methods associated with timer mock on jest objects are:

  1. jest.useFakeTimers()Instructions:JestUsing a fake version of the standard timer function (SetTimeout, setInterval, clearTimeout, clearInterval, nextTick, setImmediate and clearImmediate).
  2. jest.useRealTimers()Instructions:JestUse the real version of the standard timer feature.
  3. jest.clearAllTimers(): Clears any waiting timers from the timer system.
  4. jest.runAllTicks(): Performs all tasks in the microtask queue (usually passesprocess.nextTickJoin in the node).
  5. jest.runAllTimers(): Executes all tasks in the macro task queue.
  6. jest.runAllImmediates()Through:setImmediate()Execute all tasks in the task queue.
  7. jest.advanceTimersByTime(n): Executes all tasks in the macro task queue when theAPIWhen called, all timers are advancednSeconds.
  8. jest.runOnlyPendingTimers(): Performs only the tasks currently waiting in the macro task.

For Example (see example.5):

// timer.js function timerGame(callback) { console.log('Ready.... go! '); setTimeout(() => { console.log('Times up -- stop! '); callback && callback(); }, 1000); } module.exports = timerGame;Copy the code

In timer.js, we set a timer to execute after 1s, but the test code executes synchronously. With timer mock, we can complete the test without waiting for the timer to complete.

const timer = require('./timer');
const callback = jest.fn();

jest.useFakeTimers();

test('calls the callback after 1 second'.() = > {
    timer(callback);

    expect(callback).not.toBeCalled();

    expect(setTimeout).toHaveBeenCalledTimes(1);
    expect(setInterval).toHaveBeenCalledTimes(0);
    expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), 1000);

    jest.runAllTimers();

    expect(callback).toBeCalled();
    expect(callback).toHaveBeenCalledTimes(1);
});
Copy the code

In the above code, we have declared the use of false time in line 4. In the test block, although setTimeout has not finished executing, the test has completed. SetTimeout is executed once, and no setInterval is executed, as expected. The next call to jest.runalltimers () causes all timers to finish immediately, and the console prints the output from the timer.

In the case of recursive timer, if using a jest. RunAllTimers (), all of the timer is an infinite loop, this time you need to use jest. RunOnlyPendingTimers (). Because no new timers are generated during runOnlyPendingTimers, the problem of infinite loops is avoided, as shown in pendingTimer in Example.5.

Jest. AdvanceTimersByTime (n) is also easy to understand, which is to advance all timers by n seconds. As shown below, callback is not called until jest. AdvanceTimersByTime (n) is called, and then jest. AdvanceTimersByTime (1000) causes the timer to be executed 1s earlier, so the following assertion does not give an error.

// timer3.test.js
const timerGame = require('./timer');
const callback = jest.fn();
jest.useFakeTimers();

test('calls the callback after 1 second via advanceTimersByTime'.() = > {
    timerGame(callback);

    // At this point in time, the callback should not have been called yet
    expect(callback).not.toBeCalled();

    // Fast-forward until all timers have been executed
    jest.advanceTimersByTime(1000);

    // Now our callback should have been called!
    expect(callback).toBeCalled();
    expect(callback).toHaveBeenCalledTimes(1);
});
Copy the code

Similarly, if you use jest. AdvanceTimersByTime (500) 0.5s ahead, the above test can be modified as follows.

jest.advanceTimersByTime(500);

expect(callback).not.toBeCalled();
expect(callback).toHaveBeenCalledTimes(0);
Copy the code

Manual Mock

Manual Mock is used for the ability to store simulated data. For example, you might want to create a manual emulation that allows you to work with fake data instead of accessing remote resources such as a Web site or database. This ensures that your tests are fast and stable.

Define manual emulation by writing modules in the __mocks __ subdirectory immediately adjacent to the module. For Example, to simulate a module named User in the Models directory (as shown in example.9), create a file named user.js and place it in the Models / __ mocks__ directory. Also note that the __mocks__ folder is case sensitive.

// userMocked.test.js
import user from './models/user';

jest.mock('./models/user');

test('if user model is mocked'.() = > {
    expect(user.getAuthenticated()).toEqual({age: 622.name: 'Mock name'});
});
Copy the code

If the module you are simulating is a Node module (for example: Lodash), the mock should be placed in the __mocks__ directory adjacent to node_modules and will be simulated automatically. There is no need to explicitly call jest. Mock (‘module_name’). However, if you want to mock a core Node module (e.g. Fs or PATH), then explicitly calling for example: jest. Mock (‘path’) is required because core Node modules are not simulated by default.

If you are using ES6 module imports, you generally prefer to place import statements at the top of the test file. But in general you need to instruct Jest to use emulation before the module uses it. For this reason, Jest automatically promotes the Jest. Mock call to the top of the module (before any imports).

ES6 Class Mock

As shown in Example.6, there is a SoundPlayer class and a SoundPlayerConsumer class that uses this class. We will simulate SoundPlayer in our SoundPlayerConsumer test.

// sound-player.js export default class SoundPlayer { constructor() { this.foo = 'bar'; } playSoundFile(fileName) { console.log('Playing sound file ' + fileName); } } // sound-player-consumer.js import SoundPlayer from './sound-player'; export default class SoundPlayerConsumer { constructor() { this.soundPlayer = new SoundPlayer(); } playSomethingCool() { const coolSoundFileName = 'song.mp3'; this.soundPlayer.playSoundFile(coolSoundFileName); }}Copy the code

There are four ways to create an ES6 class simulation:

1.Automatic mock

Using this method, all the methods in the class called state saved in theAutomaticMock. Mock. Instances [index]. MethodName. Mock. Calls. Also, if you use arrow functions in your class, they will not be part of the simulation. Because arrow functions do not exist on the prototype of the object, they are just properties that contain references to the function.

Note: Since both Automatic mock and Manual mock exist in Example.6, you need to rename the __mocks__ folder when using this method.

2.Manual mock

Substitution emulation is performed by generating a file of the same name under an adjacent __mocks__ folder.

Note: Make sure the __mocks__ folder is named correctly when using Manual Mock.

3.Calling jest.mock() with the module factory parameter

Mock (Path, moduleFactory) takes the moduleFactory argument, and moduleFactory returns a mock function. To simulate a constructor, the moduleFactory must return a constructor; in other words, the moduleFactory must be a function that returns a function.

4.Replacing the mock using mockImplementation() or mockImplementationOnce()

The call to jest. Mock is promoted to the top of the code. Instead of using the factory parameter, you can specify the mock later (for example, in beforeAll()), or change the mock between tests, by calling mockImplementation() (or mockImplementationOnce()) on an existing mock.

Bypassing Module Mock

Jest allows you to simulate entire modules in your tests, which helps test whether the code is correct and the function calls are correct. However, sometimes you may want to use part of a mock module in a test file, in which case you want access to the original implementation rather than the mock version. Jest. RequireActual () allows you to import the actual version, not the mock version.

conclusion

Mock functions allow us to better write our test code with three features:

  • Capture function calls
  • Sets the return value of the function
  • Change the internal implementation of a function

In the unit tests of the actual project:

  • Jest.fn () is often used for some tests with callback functions;

  • Jest. Mock () can mock methods in an entire module. When a module is 100% covered by a unit test, using jest. Mock () is necessary to save test time and redundancy.

  • Jest. SpyOn () is often used when you need to test some method that must be executed in its entirety;

All of these need to be flexibly chosen by the developer based on the actual business code.

Official Documents section

Mock functions allow you to test connections between code by erasing the actual implementation of functions, capturing calls to functions (and arguments passed in those calls), capturing constructor instances when instantiating with new, and allowing you to configure return values when testing.

There are two ways to simulate functions: either create a mock function in the test code, or write a manual mock to override module dependencies.

Using mock functions

Suppose we want to test the internal implementation of the function forEach, which calls the callback once forEach element in the passed array.

function forEach(items, callback) {
  for (let index = 0; index < items.length; index++) { callback(items[index]); }}Copy the code

To test this function, we can use a mock function and then check the state of the mock function to ensure that the callback function is called as expected.

const mockCallback = jest.fn(x= > 42 + x);
forEach([0.1], mockCallback);

// This mock function is called twice
expect(mockCallback.mock.calls.length).toBe(2);

// The first argument to the function is 0
expect(mockCallback.mock.calls[0] [0]).toBe(0);

// The second time the function is called, the first argument is 1
expect(mockCallback.mock.calls[1] [0]).toBe(1);

// The return value of the first function call is 42
expect(mockCallback.mock.results[0].value).toBe(42);
Copy the code

.mockattribute

All mock functions have this special.mock attribute, which holds information about how the function was called and the value returned when it was called. The.mock property also tracks the value of this on each call, so we can also inspect this:

const myMock = jest.fn();

const a = new myMock();
const b = {};
const bound = myMock.bind(b);
bound();

console.log(myMock.mock.instances);
// > [ <a>, <b> ]
Copy the code

These mock member variables are useful in testing to illustrate how these functions are called, instantiated, or returned:

// This function is called only once
expect(someMockFunction.mock.calls.length).toBe(1);

// The first arg when this function is first called is 'first arg'
expect(someMockFunction.mock.calls[0] [0]).toBe('first arg');

// The first time this function is called the second arg is 'second arg'
expect(someMockFunction.mock.calls[0] [1]).toBe('second arg');

// This function is instantiated twice
expect(someMockFunction.mock.instances.length).toBe(2);

// The first instantiation of this function returns an object with a name attribute set to 'test '.
expect(someMockFunction.mock.instances[0].name).toEqual('test');
Copy the code

The return value of the Mock

Mock functions can also be used to inject test values into code during testing:

const myMock = jest.fn();
console.log(myMock());
// > undefined

myMock.mockReturnValueOnce(10).mockReturnValueOnce('x').mockReturnValue(true);

console.log(myMock(), myMock(), myMock(), myMock());
// > 10, 'x', true, true
Copy the code

Mock functions can also be useful in code that functions continuation-passing style. This code style helps to avoid complex intermediate operations and visualize the true intent of components, which makes it easier to inject values directly into tests before they are called.

const filterTestFn = jest.fn();

// Make the mock return `true` for the first call,
// and `false` for the second call
filterTestFn.mockReturnValueOnce(true).mockReturnValueOnce(false);

const result = [11.12].filter(num= > filterTestFn(num));

console.log(result);
/ / > [11]
console.log(filterTestFn.mock.calls[0] [0]); / / 11
console.log(filterTestFn.mock.calls[1] [0]); / / 12
Copy the code

In most real-world examples, you actually attach a mock function to the dependent component and configure it, but the approach is the same. In these cases, try to avoid implementing logic in any function you don’t really want to test.

Simulation module

Suppose you have a class that gets users from an API. This class calls the API using AXIos and returns data, which contains attributes for all users:

// users.js
import axios from 'axios';

class Users {
  static all() {
    return axios.get('/users.json').then(resp= >resp.data); }}export default Users;
Copy the code

To test this method without actually calling the API (making the test slow and vulnerable), we can use jest. Mock (…) Function automatically emulates the AXIOS module.

Once the module is emulated, we can provide a mockResolvedValue for.get, which will return dummy data for testing. Equivalent, we want axios.get(‘/users.json’) to return a false response

// users.test.js
import axios from 'axios';
import Users from './users';

jest.mock('axios');

test('should fetch users'.() = > {
  const users = [{name: 'Bob'}];
  const resp = {data: users};
  axios.get.mockResolvedValue(resp);

  // or you could use the following depending on your use case:
  // axios.get.mockImplementation(() => Promise.resolve(resp))

  return Users.all().then(data= > expect(data).toEqual(users));
});
Copy the code

The Mock implementation

In some cases it can be useful to Mock out a specified return value. Mock functions can be implemented using either the jest. Fn or the mockImplementationOnce method.

const myMockFn = jest.fn(cb= > cb(null.true));

myMockFn((err, val) = > console.log(val));
// > true
Copy the code

The mockImplementation method is useful when you need to define default Mock function implementations based on other modules.

// foo.js
module.exports = function () {
  // some implementation;
};

// test.js
jest.mock('.. /foo'); // this happens automatically with automocking
const foo = require('.. /foo');

// foo is a mock function
foo.mockImplementation(() = > 42);
foo();
/ / > 42
Copy the code

Use the mockImplementationOnce method when you need to simulate a function call that returns a different result

const myMockFn = jest
  .fn()
  .mockImplementationOnce(cb= > cb(null.true))
  .mockImplementationOnce(cb= > cb(null.false));

myMockFn((err, val) = > console.log(val));
// > true

myMockFn((err, val) = > console.log(val));
// > false
Copy the code

When the implementation of the mockImplementationOne definition is called one by one, jest. Fn will be used if it is defined.

const myMockFn = jest
  .fn(() = > 'default')
  .mockImplementationOnce(() = > 'first call')
  .mockImplementationOnce(() = > 'second call');

console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
// > 'first call', 'second call', 'default', 'default'
Copy the code

In most cases, our function calls are chained. If you want to create a function that supports chained calls (because this is returned), use the.mockReturnThis() function to do so.

const myObj = {
  myMethod: jest.fn().mockReturnThis(),
};

// is the same as

const otherObj = {
  myMethod: jest.fn(function () {
    return this; })};Copy the code

The name of the Mock

  • .mockName()

You can name your Mock function instead of jest.fn() in the error output of the unit test. This way you can quickly find your Mock functions in the unit test output log.

const myMockFn = jest
  .fn()
  .mockReturnValue('default')
  .mockImplementation(scalar= > 42 + scalar)
  .mockName('add42');
Copy the code

Custom matcher

Testing Mock functions requires a lot of assertion writing, and to reduce the amount of code we provide some custom matchers.

// The mock function was called at least once
expect(mockFunc).toHaveBeenCalled();

// The mock function was called at least once with the specified args
expect(mockFunc).toHaveBeenCalledWith(arg1, arg2);

// The last call to the mock function was called with the specified args
expect(mockFunc).toHaveBeenLastCalledWith(arg1, arg2);

// All calls and the name of the mock is written as a snapshot
expect(mockFunc).toMatchSnapshot();
Copy the code

These matchers are syntactic sugars for asserting Mock functions. You can choose your own matchers according to your own needs.

// The mock function was called at least once
expect(mockFunc.mock.calls.length).toBeGreaterThan(0);

// The mock function was called at least once with the specified args
expect(mockFunc.mock.calls).toContainEqual([arg1, arg2]);

// The last call to the mock function was called with the specified args
expect(mockFunc.mock.calls[mockFunc.mock.calls.length - 1]).toEqual([
  arg1,
  arg2,
]);

// The first arg of the last call to the mock function was `42`
// (note that there is no sugar helper for this specific of an assertion)
expect(mockFunc.mock.calls[mockFunc.mock.calls.length - 1] [0]).toBe(42);

// A snapshot will check that a mock was invoked the same number of times,
// in the same order, with the same arguments. It also asserts on the name.
expect(mockFunc.mock.calls).toEqual([[arg1, arg2]]);
expect(mockFunc.getMockName()).toBe('a mock name');
Copy the code

Summary of common methods

Mock functions:

  1. MockFn. MockName (Value) : Sets the name of the mock function

  2. Mockfn.getmockname () : Returns the name set in mockfn.mockName (value)

  3. Mockfn. mock. Calls: Mock function call information

Mockfn.mock. Calls returns an array, each element of which is an array containing the mock function call information. For example, if a mock function f is called twice with f(‘arg1’, ‘arg2’) and then uses f(‘arg3’, ‘arg4’), mockfn.mock. Calls returns an array of the following form:

[[‘ arg1, arg2 ‘], [‘ arg3 ‘, ‘arg4]]

Mockfn.mock.calls. length therefore represents the number of times the mock function has been called, mockfn.mock. calls[0][0] represents the first argument passed in for the first call, and so on.

  1. Mockfn.mock. Results: The return value of the mock function, stored as an array

  2. Mockfn. mock. Instances: Instances of mock functions

const mockFn = jest.fn();

const a = new mockFn();
const b = new mockFn();

mockFn.mock.instances[0] === a; // true
mockFn.mock.instances[1] === b; // true
Copy the code
  1. mockFn.mockImplementation(fn): Create amockfunction

Note: jest.fn(implementation) is short for jest.fn().mockImplementation(implementation).

  1. mockFn.mockImplementationOnce(fn): Create amockfunction

This function will be used as an implementation of the mock for a call to mocked. You can chain calls so that multiple function calls produce different results.

const myMockFn = jest
  .fn()
  .mockImplementationOnce(cb => cb(null, true))
  .mockImplementationOnce(cb => cb(null, false));

myMockFn((err, val) => console.log(val)); // true

myMockFn((err, val) => console.log(val)); // false
Copy the code

When mocked functions run out of implementation defined using mockImplementationOnce, if they are called, It will execute the default implementation set using jest.fn(()=> defaultValue) or.mockImplementation(()=> defaultValue) :

const myMockFn = jest
  .fn(() => 'default')
  .mockImplementationOnce(() => 'first call')
  .mockImplementationOnce(() => 'second call');

// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
Copy the code
  1. mockFn.mockReturnThis():jest.fn()The syntactic sugar
jest.fn(function() {
  return this;
});
Copy the code
  1. mockFn.mockReturnValue(value): accepts a value as the callmockFunction
const mock = jest.fn(); mock.mockReturnValue(42); mock(); // 42 mock.mockReturnValue(43); mock(); / / 43Copy the code
  1. mockFn.mockReturnValueOnce(value): accepts a value as the callmockFunction, which can be called in chain order to produce different results.

When the mockReturnValueOnce value is no longer used, the call returns the value specified by mockReturnValue.

const myMockFn = jest
  .fn()
  .mockReturnValue('default')
  .mockReturnValueOnce('first call')
  .mockReturnValueOnce('second call');

// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
Copy the code
  1. mockFn.mockResolvedValue(value):mockSyntactic sugar for asynchronous functions

The implementation is similar to

jest.fn().mockImplementation(() => Promise.resolve(value));
Copy the code

Used to simulate asynchronous functions in test

test('async test', async () => {
  const asyncMock = jest.fn().mockResolvedValue(43);

  await asyncMock(); // 43
});
Copy the code
  1. mockFn.mockResolvedValueOnce(value): syntactic sugar

The implementation is similar to

jest.fn().mockImplementationOnce(() => Promise.resolve(value));
test('async test', async () => {
  const asyncMock = jest
    .fn()
    .mockResolvedValue('default')
    .mockResolvedValueOnce('first call')
    .mockResolvedValueOnce('second call');

  await asyncMock(); // first call
  await asyncMock(); // second call
  await asyncMock(); // default
  await asyncMock(); // default
});
Copy the code
  1. mockFn.mockRejectedValue(value): syntactic sugar

The implementation is similar to

jest.fn().mockImplementation(() => Promise.reject(value));
test('async test', async () => {
  const asyncMock = jest.fn().mockRejectedValue(new Error('Async error'));

  await asyncMock(); // throws "Async error"
});
Copy the code
  1. mockFn.mockRejectedValueOnce(value): syntactic sugar

The implementation is similar to

jest.fn().mockImplementationOnce(() => Promise.reject(value));
test('async test', async () => {
  const asyncMock = jest
    .fn()
    .mockResolvedValueOnce('first call')
    .mockRejectedValueOnce(new Error('Async error'));

  await asyncMock(); // first call
  await asyncMock(); // throws "Async error"
});
Copy the code
  1. mockFn.mockClear(): resets all stored inmockFn.mock.callsmockFn.mock.instancesInformation in an array

This is often useful when you want to clear analog usage data between two assertions.

  1. mockFn.mockReset()Completed:mockFn.mockClear()All things done, but also remove any simulated return values or implementations

This is useful when you want to completely reset the simulation back to its original state. Note that resetting the Spy causes the function to return no value.

  1. mockFn.mockRestore()Completed:mockFn.mockReset()All the things you do, and restore the original (non-simulated) implementation

This is useful when you want to simulate a function in some test cases and restore the original implementation in others.

Reference documentation

  • Jest Unit Test Primer and Examples (juejin. Cn)

  • Test JavaScript with Jest (Mock) – SegmentFault think no

  • Jest start guide | ice, water and cold in water (iceiceice. Top)

  • The official documentation