The highlight of this answer is jest.requireActual(), this is a very useful utility that says to jest that "Hey keep every original functionalities intact and import them".
Copyjest.mock('./utilities.js', () => ({
...jest.requireActual('./utilities.js'),
speak: jest.fn(),
}));
Let's take another common scenario, you're using enzyme ShallowWrapper and it doesn't goes well with useContext() hook, so what're you gonna do? While i'm sure there are multiple ways, but this is the one I like:
Copyimport React from "react";
jest.mock("react", () => ({
...jest.requireActual("react"), // import and retain the original functionalities
useContext: jest.fn().mockReturnValue({foo: 'bar'}) // overwrite useContext
}))
The perk of doing it this way is that you can still use
import React, { useContext } from "react" in your original code without worrying about converting them into React.useContext() as you would if you're using jest.spyOn(React, 'useContext')
The highlight of this answer is jest.requireActual(), this is a very useful utility that says to jest that "Hey keep every original functionalities intact and import them".
Copyjest.mock('./utilities.js', () => ({
...jest.requireActual('./utilities.js'),
speak: jest.fn(),
}));
Let's take another common scenario, you're using enzyme ShallowWrapper and it doesn't goes well with useContext() hook, so what're you gonna do? While i'm sure there are multiple ways, but this is the one I like:
Copyimport React from "react";
jest.mock("react", () => ({
...jest.requireActual("react"), // import and retain the original functionalities
useContext: jest.fn().mockReturnValue({foo: 'bar'}) // overwrite useContext
}))
The perk of doing it this way is that you can still use
import React, { useContext } from "react" in your original code without worrying about converting them into React.useContext() as you would if you're using jest.spyOn(React, 'useContext')
The most straightforward way is to use jest.spyOn and then .mockImplementation(). This will allow all other functions in the module to continue working how they're defined.
For packages:
Copyimport axios from 'axios';
jest.spyOn(axios, 'get');
axios.get.mockImplementation(() => { /* do thing */ });
For modules with named exports:
Copyimport * as utils from './utilities.js';
jest.spyOn(utils, 'speak');
utils.speak.mockImplementation(() => { /* do thing */ });
Docs here: https://jestjs.io/docs/en/jest-object#jestspyonobject-methodname
How to mock only a non-default function in Jest
Testing Jest Problem: Cannot mock and unmock in the same file
Jest Mocking.. mocking an internal property of a factory function
How to have multiple mock return values for a method within a class within a module?
I am trying to mock a non default function in jest which is part of a larger module and I don't want to mock any of the rest of it. I tried something along the lines of the solution found here (https://stackoverflow.com/questions/59312671/mock-only-one-function-from-module-but-leave-rest-with-original-functionality). The problem is that importing the default function gives you the whole module instead of the default function.
For example:
// myModule.js
export const foo = () => {
console.log("in foo");
};
const bar = () => {
console.log("in bar");
};
export default bar;// useMyModule.test.js
import bar, { foo } from "./myModule";
import "./useMyModule";
jest.mock("./myModule", () => ({
...jest.requireActual("./myModule"),
foo: jest.fn(() => {
console.log("in test foo");
}),
}));
test("see if this works", () => {
console.log(bar);
foo();
});
// useMyModule.js import bar from "./myModule"; console.log(bar); //bar(); // <== commented out because bar is not the function I expect it to be
This is what the output looks like:
PASS src/useMyModule.test.js
● Console
console.log
{
default: [Function: bar],
foo: [Function: mockConstructor] {
_isMockFunction: true,
getMockImplementation: [Function (anonymous)],
mock: [Getter/Setter],
mockClear: [Function (anonymous)],
mockReset: [Function (anonymous)],
mockRestore: [Function (anonymous)],
mockReturnValueOnce: [Function (anonymous)],
mockResolvedValueOnce: [Function (anonymous)],
mockRejectedValueOnce: [Function (anonymous)],
mockReturnValue: [Function (anonymous)],
mockResolvedValue: [Function (anonymous)],
mockRejectedValue: [Function (anonymous)],
mockImplementationOnce: [Function (anonymous)],
mockImplementation: [Function (anonymous)],
mockReturnThis: [Function (anonymous)],
mockName: [Function (anonymous)],
getMockName: [Function (anonymous)]
}
}
at Object.<anonymous> (src/useMyModule.js:3:9)
console.log
{
default: [Function: bar],
foo: [Function: mockConstructor] {
_isMockFunction: true,
getMockImplementation: [Function (anonymous)],
mock: [Getter/Setter],
mockClear: [Function (anonymous)],
mockReset: [Function (anonymous)],
mockRestore: [Function (anonymous)],
mockReturnValueOnce: [Function (anonymous)],
mockResolvedValueOnce: [Function (anonymous)],
mockRejectedValueOnce: [Function (anonymous)],
mockReturnValue: [Function (anonymous)],
mockResolvedValue: [Function (anonymous)],
mockRejectedValue: [Function (anonymous)],
mockImplementationOnce: [Function (anonymous)],
mockImplementation: [Function (anonymous)],
mockReturnThis: [Function (anonymous)],
mockName: [Function (anonymous)],
getMockName: [Function (anonymous)]
}
}
at Object.<anonymous> (src/useMyModule.test.js:12:13)However, if you uncomment the bar() invocation above, you get this:
FAIL src/useMyModule.test.js
● Test suite failed to run
TypeError: (0 , _myModule.default) is not a function
2 |
3 | console.log(bar);
> 4 | bar();
| ^
5 |
at Object.<anonymous> (src/useMyModule.js:4:4)
at Object.<anonymous> (src/useMyModule.test.js:2:1)So, how should I mock the foo function, but leave the default bar function intact?