我只想从模块中模拟一个函数(名为export),但保持模块的其余函数不变。
使用jest.mock('package-name')
会使所有导出的函数都成为mock,这是我不希望看到的。
我试着将指定的导出扩展回mock对象.
import * as utils from './utilities.js';
jest.mock(utils, () => ({
...utils
speak: jest.fn(),
}));
字符串
但得到了这个错误:jest.mock()
的模块工厂不允许引用任何范围外的变量。
6条答案
按热度按时间mrphzbgm1#
这个答案的亮点是jest.requireActual(),这是一个非常有用的实用程序,它说:“嘿,保持每个原始功能的完整性并导入它们”。
字符串
让我们来看看另一个常见的场景,你正在使用酶ShallowWrapper,它与useContext()钩子不匹配,所以你要做什么?虽然我相信有多种方法,但这是我喜欢的一种:
型
这样做的好处是,您仍然可以在原始代码中使用
import React, { useContext } from "react"
,而不必担心将它们转换为React.useContext(),就像您使用**jest.spyOn(React,'useContext')**一样。gg0vcinb2#
最直接的方法是先使用
jest.spyOn
,然后再使用.mockImplementation()
。这将允许模块中的所有其他函数继续按照它们的定义工作。对于包裹:
字符串
对于具有命名导出的模块:
型
网址:https://jestjs.io/docs/en/jest-object#jestspyonobject-methodname
vatpfxk53#
jest.mock
内部的jest.requireActual
似乎是要走的路,但是我需要添加一个代理而不是对象扩展,以防止在某些导入场景中可能发生的类型错误Cannot read properties of undefined (reading ...)
。这是最后的结果:
字符串
5lwkijsr4#
对我来说,这是有效的:
字符串
czq61nw15#
我接受了Rico Kahler的答案,并创建了这个通用函数:
字符串
你可以这样使用它来模拟lodash:
型
laximzn56#
我建议考虑设置mock,以便它继续调用原始函数,直到mock被显式重置,并在对被模拟的函数感兴趣的测试之前设置所需的mock行为。
字符串
为了解释为什么,大多数答案在大多数情况下都有效,但是对于核心或外部库中的任何模块,如果被多个其他导入使用,它们可能会产生副作用。
当你使用
jest.mock("<name>")
时,它会在实际执行导入之前应用。查看https://jestjs.io/docs/mock-functions#mocking-modules你可以看到mock是在导入之后,但它仍然按照预期工作。然而在https://jestjs.io/docs/bypassing-module-mocks中,mock是在导入之前创建的,这可能并不明显,即使后来的jest hook足够早,可以在处理导入中的内容之前应用mock。这意味着任何被导入并试图创建一个对象的具体示例以设置为模块属性的东西都将获得模拟示例而不是原始示例。
在某些情况下,这可能是预期的,但更有可能是令人惊讶的。通过最初将mock传递到原始调用,它允许其他导入初始设置使用该函数,然后可以在测试调用它的函数之前切换到使用所需的mock实现。
显然,如果你在模仿你写的东西,这就不那么重要了,更多的是在使用库和框架时,这些库和框架可能有你可能没有完全意识到的依赖关系和行为。
在我的例子中,我被GitHub的
@actions/toolkit
中的上下文对象咬了一口,希望在加载时读取JSON文件,这只会在设置GITHUB_EVENT_PATH
env var时引起问题。https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts