仅模拟模块中的一个函数,但保留原始功能

2022-08-30 04:15:21

我只想从模块中模拟单个函数(名为export),但保留模块函数的其余部分不变。

使用使所有导出的函数模拟,这是我不想要的。jest.mock('package-name')

我尝试将命名的导出传播回模拟对象...

import * as utils from './utilities.js';

jest.mock(utils, () => ({
  ...utils
  speak: jest.fn(),
}));

但得到这个错误:

不允许 的模块工厂引用任何超出范围的变量。jest.mock()


答案 1

这个答案的亮点是jest.requireActual(),这是一个非常有用的实用程序,它说“嘿,保持每个原始功能完好无损并导入它们”。

jest.mock('./utilities.js', () => ({
  ...jest.requireActual('./utilities.js'),
  speak: jest.fn(),
}));

让我们以另一个常见的场景为例,你正在使用酶ShallowWrapper,它与useContext()钩子不太配合,那么你打算做什么呢?虽然我确信有多种方式,但这是我喜欢的:

import React from "react";

jest.mock("react", () => ({
  ...jest.requireActual("react"), // import and retain the original functionalities
  useContext: jest.fn().mockReturnValue({foo: 'bar'}) // overwrite useContext
}))

这样做的好处是,你仍然可以在原始代码中使用,而不必担心将它们转换为React.useContext(),就像你使用jest.spyOn(React,'useContext')一样。import React, { useContext } from "react"


答案 2

最直接的方法是使用,然后。这将允许模块中的所有其他函数继续按照定义的方式工作。jest.spyOn.mockImplementation()

对于软件包:

import axios from 'axios';

jest.spyOn(axios, 'get');
axios.get.mockImplementation(() => { /* do thing */ });

对于具有命名导出的模块:

import * as utils from './utilities.js';

jest.spyOn(utils, 'speak');
utils.speak.mockImplementation(() => { /* do thing */ });

此处的文档: https://jestjs.io/docs/en/jest-object#jestspyonobject-methodname