如何用Jest测试函数内部的函数调用?遇ESM适配问题
Jest测试函数调用问题解决方案
问题背景
我已经用给出的第一个方案解决了问题。之前在Jest中缺少Babel配置,我使用了Jest文档中提到的实验性ES6+设置,要求移除转换配置、添加测试命令node --experimental-vm-modules node_modules/jest/bin/jest.js等,但我不太清楚这些设置的作用,本以为是解决这类问题的,但显然不是。
我查阅了很多相关帖子并尝试了多种方案,但都无效。请问如何用Jest测试init函数内部是否调用了calling函数?
我的代码
calling.js
const calling = () => { return 'calling'; }; export default calling;
init.js
import calling from './calling'; export const init = () => { calling(); };
test.spec.js
import { jest } from '@jest/globals'; import init from './init.js'; import calling from './calling.js'; test('init calls calling', () => { // 这里该怎么写? });
package.json
{ "name": "testing", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js" }, "type": "module", "jest": { "transform": {}, "roots": [ "<rootDir>" ], "modulePaths": [ "<rootDir>" ], "moduleDirectories": [ "node_modules" ] }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@types/jest": "^28.1.8", "jest": "^28.1.3" } }
当前遇到的问题
现在基于上述方案勉强能运行,但有问题!我必须做更复杂的配置才能运行,不知道原因。而且我只能使用命名导出,因为默认导出无法生效,我也不知道如何解决这个问题。
当前测试代码:
import { jest } from '@jest/globals'; const mock = jest.fn(); jest.unstable_mockModule('./calling.js', () => ({ calling: mock, })); const { calling } = await import('./calling.js'); const { init } = await import('./init.js'); test('test', async () => { init(); expect(calling).toHaveBeenCalled(); });
解决方案
问题出在你对默认导出的mock方式不对。因为calling.js用的是默认导出,所以在jest.unstable_mockModule中需要返回default字段,而不是命名导出的calling。修改后的测试代码如下:
import { jest } from '@jest/globals'; const mockCalling = jest.fn(); // 针对默认导出进行mock jest.unstable_mockModule('./calling.js', () => ({ default: mockCalling, })); // 正确导入默认导出的mock函数 const calling = (await import('./calling.js')).default; const { init } = await import('./init.js'); test('init calls calling', () => { init(); expect(mockCalling).toHaveBeenCalled(); });
说明
- 因为你的
calling是默认导出,所以mock模块时必须指定default属性,这样init.js中导入的默认导出才会被替换成mock函数。 - 导入时要通过
(await import('./calling.js')).default获取默认导出的mock函数,而不是解构calling。 - 直接断言mock函数
mockCalling是否被调用即可,这样就能正确验证init内部是否执行了calling函数。
内容的提问来源于stack exchange,提问作者Nicolas
相关产品推荐
相关产品推荐

