如何用Jest单元测试检测JS函数是否被调用?导入函数设Spy报错排查
嘿,我来帮你搞定这两个Jest单元测试的问题!
1. 如何在Jest中检测函数是否被调用过?
Jest提供了几种直观的方式来验证函数调用情况,分两种常见场景说明:
测试本地定义的函数
用jest.fn()把目标函数包装成模拟函数,调用后用Jest的断言方法验证即可:// 示例本地函数 function calculateSum(a, b) { return a + b; } test('验证calculateSum是否被调用', () => { // 用jest.fn()包装原函数,生成带调用记录的模拟函数 const mockCalculateSum = jest.fn(calculateSum); // 调用模拟函数 mockCalculateSum(2, 3); // 断言函数被调用过 expect(mockCalculateSum).toHaveBeenCalled(); // 还可以断言调用次数 expect(mockCalculateSum).toHaveBeenCalledTimes(1); // 甚至断言调用时传入的参数 expect(mockCalculateSum).toHaveBeenCalledWith(2, 3); });测试导入模块中的函数
如果函数来自其他模块,用jest.spyOn()创建间谍函数——它会保留原函数功能,同时记录调用细节:// 假设从utils.js导入了fetchData函数 import * as utils from './utils'; test('验证utils.fetchData是否被调用', () => { // 创建间谍函数,监听utils模块下的fetchData const fetchSpy = jest.spyOn(utils, 'fetchData'); // 执行会触发fetchData的代码(比如调用依赖它的业务函数) loadUserData(); // 断言函数被调用 expect(fetchSpy).toHaveBeenCalled(); // 测试完成后恢复原函数,避免影响其他测试用例 fetchSpy.mockRestore(); });
2. 解决「TypeError: Cannot read property '_isMockFunction' of undefined」报错
这个报错的核心原因是:你要监听的函数没被Jest找到,导致创建的间谍对象是undefined,访问它的_isMockFunction属性时就触发了错误。结合你提到的export TDD:写法,大概率是导出语法有问题,或者监听目标不匹配,给你一步步排查:
第一步:修正导出语法
你写的export TDD:存在语法错误,正确的导出方式应该是这几种:
// 方式1:命名导出普通函数 export function TDD() { // 你的函数逻辑 } // 方式2:命名导出箭头函数 export const TDD = () => { // 你的函数逻辑 }; // 方式3:默认导出函数 export default function TDD() { // 你的函数逻辑 }
第二步:确保监听目标正确
如果是命名导出的TDD,导入和监听代码要对应:
// 用命名导入的方式引入整个模块 import * as myModule from './your-module-path'; test('监听TDD函数', () => { // 先确认模块中确实导出了TDD函数 if (!myModule.TDD) { throw new Error('模块中未找到导出的TDD函数'); } // 创建间谍函数 const tddSpy = jest.spyOn(myModule, 'TDD'); // 执行触发TDD的代码 callFunctionThatUsesTDD(); // 断言函数被调用 expect(tddSpy).toHaveBeenCalled(); // 恢复原函数 tddSpy.mockRestore(); });
如果是默认导出的TDD,jest.spyOn不太好直接使用,你可以直接模拟整个模块的默认导出:
import TDD from './your-module-path'; // 把模块的默认导出替换为jest模拟函数 jest.mock('./your-module-path', () => ({ __esModule: true, default: jest.fn() })); test('验证默认导出的TDD是否被调用', () => { // 执行触发TDD的代码 triggerTDD(); expect(TDD).toHaveBeenCalled(); });
另外要注意:别在创建间谍函数之前就执行调用TDD的代码,否则间谍还未生效,也可能导致后续断言出问题。
内容的提问来源于stack exchange,提问作者Donovant
相关产品推荐
相关产品推荐

