Creating Mock Objects

Learn to create mock functions and objects. You will also learn to specify their side effects and return values.

Mock functions

As you probably remember from earlier, you can create a mock function like this:

const mockFn = jest.fn();

You can specify its return values like:

mockFn.mockReturnValueOnce(42);

This line will make mockFn return 42 when called. However, it will only work once. To make it return 42 always, write:

mockFn.mockReturnValue(42);

If the scenario is more complicated, you may want to return different values on every function invocation. To do this, you can chain mockReturnValueOnce calls:

mockFn
  .mockReturnValueOnce(1)
  .mockReturnValueOnce('two')
  .mockReturnValueOnce(3);

console.log(mockFn()); // 1
console.log(mockFn()); // 'two'
console.log(mockFn()); // 3

Sometimes, you want to mock the whole implementation of the function and not just the return value. You can use the mockImplementation/mockImplementationOnce functions for that:

const mockFn = jest.fn();
mockFn.mockImplementationOnce(() => console.log('it works'));

mockFn();
// it works

mockImplementation is also used to throw exceptions from mock functions:

const thisShouldThrow = jest.fn();
thisShouldThrow.mockImplementation(() => {
  throw new Error('it works');
});
thisShouldThrow();
// Uncaught Error: it works

Verifying mock functions

Mock functions would not be particularly useful if there was no way of validating the interactions on them. You should already know some of the functions like expect(fn).toHaveBeenCalled and expect(fn).toHaveBeenCalledWith. Here are some more functions that you will find useful:

  • expect(fn).toHaveBeenLastCalledWith(args): Verify that the last call was made with specified arguments.
  • expect(fn).toHaveBeenCalledTimes(n): Verify that fn was called exactly n times.
  • expect(fn).toHaveBeenNthCalledWith(n, args): Verify that fn was called with specified arguments on exactly the nth^{th} call.

If these assertions are not enough for your tests, you can access the calls directly. Every mock function will have the mock property. In turn, it has the calls property. calls is an array of arrays:

const mockFn = jest.fn();
mockFn(5);
mockFn('Toyobara', 'BRZ');

console.log(mockFn.mock.calls.length); // 2
console.log(mockFn.mock.calls[0][0]); // 5
console.log(mockFn.mock.calls[1]); // ['Toyobara', 'BRZ']

Using these objects, you can test for any interaction possible.

Quick recap

In this lesson, we learned some advanced functions to work with mocks. You should now know how to specify the return values of mock functions and their side effects as well as how to assert on their calls and arguments. We used the following functions from Jest:

  • jest.fn() to create mock functions.
  • fn.mockReturnValue/fn.mockReturnValueOnce to specify return values for mocks.
  • fn.mockImplementation/fn.mockImplementationOnce to specify implementation or throw errors from mocks.
  • expect(fn).toHaveBeenCalled/expect(fn).toHaveBeenCalledWith(args) to assert on any calls.
  • expect(fn).toHaveBeenLastCalledWith(args) to assert on last call.
  • expect(fn).toHaveBeenNthCalledWith(n, args) to assert on nth call.
  • fn.mock.calls to assert on anything else.

Get hands-on with 1200+ tech skills courses.