Mock functions allow you to test the links between code by erasing the actual implementation of a function, capturing calls to the function (and the parameters passed in those calls), capturing instances of constructor functions when instantiated with new, and allowing test-time configuration of return values.
There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a manual mock to override a module dependency.
jest.mock
Shallow replacement/behavior control of a module or function.
Default mock creates a mock function that, by default, returns undefined
.
import method from 'libs/package/method'; // mocking the path jest.mock('libs/package/method'); // default export that is a function jest.mock('libs/package/method', () => jest.fn()); // default export with constant return value jest.mock('libs/package/method', () => jest.fn(() => "string return value")); // default export with return as esModule object jest.mock('libs/package/method', () => ({ __esModule: true, // indicate to Jest this is a module default: jest.fn(), // mock default export }));
import { useHook } from 'lib/hooks'; // mocking a method imported jest.mock('lib/useHook', () => jest.fn()); // path must match import path describe('some test', () => { const useHookMock = jest.mocked(useHook); beforeAll(() => { useHookMock.mockReturnValue(true); }); });
This is the preferred way using Typescript:
import { someMethod } from 'lib/domain/helpers/someMethod'; jest.mock('lib/domain/helpers/someMethod', () => ({ someMethod: jest.fn(), // jest would identify this as a valid function })); const mockedSomeMethod = someMethod as jest.Mock; describe('test someMethod', () => { mockedSomeMethod.mockedReturnValueOnce("mocked return value"); // OR (someMethod as jest.Mock).mockResolvedValue("mocked resolved value"); });
import {someMethod, anotherMethod} from 'libs/package/method'; jest.mock('libs/package/method', () => ({ someMethod: jest.fn(), anotherMethod: jest.fn(), })); // assertion const expectedResult = { someField: "expected value", anotherField: "another value", }; expect()
Have been called:
import {someMethod} from 'libs/package/method'; jest.mock('libs/package/method', () => jest.fn()); const mockedSomeMethod = jest.mocked(someMethod); expect(mockedSomeMethod).toHaveHaveBeenCalledWith()
mockDeep
mockDeep
is a utility function in jest-mock-extended
library that will mock deeply nested attributes of an object.
Avoids having to do the nesting yourself like:
jest.mock('someModule', () => ({ field: { subfield: { nestedfield: jest.fn, }} }));
Instead:
import {mockDeep} from 'jest-mock-extended'; import {someModule} from 'lib/someModule'; const mockedModule = mockDeep(someModule);
serializes to the same string
Received: serializes to the same string
indicates that returned object may be valid comparison, but is a stringed version of it:
Convert either the expectation or the passed result to a consistent data type for comparison.
JSON.stringify()
If you're using toBe()
comparison, switch to toEqual()
.
TypeError: (0, methodName_1.default) is not a function
TypeError: (0, methodName_1.default) is not a function
When a module is a default export
and imported, use the following syntax:
import someMethod from 'some-domain/someMethod'; jest.mock('some-domain/someMethod', () => ({ __esModule: true, // indicate to Jest this is a module default: jest.fn(), // mock default export })); // mocking resolved value beforeEach(async () => { (someMethod as jest.Mock).mockResolvedValue("some resolved value"); }); // assertion expect(someMethod).toHaveBeenCalledTimes(1);
TypeError: Cannot destructure property 'html' of '(0, mjml_react1.render)(...)' as it is undefined.
TypeError: Cannot destructure property 'html' of '(0, mjml_react1.render)(...)' as it is undefined.
Failing because mjml.render
was mocked not as a function with a return value:
// incorrect jest.mock('mjml-react', () => ({ render: jest.fn(), })); // correct jest.mock('mjml-react', () => ({ render: jest.fn().mockResolvedValue({ html: "", errors: [], }), }));