如何在不修改原JS文件的情况下用Jest测试全局函数?
解决Jest测试未导出全局异步函数的问题
因为你的函数是通过HTML <script> 标签引入的全局函数,没有模块导出,Jest默认运行在Node环境,直接require后找不到函数。可以通过以下两种方式解决:
方案一:使用jsdom模拟浏览器环境
Jest支持切换到jsdom环境(模拟浏览器的DOM和全局对象),让全局函数自动挂载到window对象上:
配置Jest使用jsdom环境
修改你的jest.config.js(或者在package.json的jest字段里添加配置):module.exports = { testEnvironment: 'jsdom', // 保留其他现有配置 };在测试文件中访问全局函数
直接require目标JS文件,函数会自动挂载到window,即可直接调用测试:// 引入全局函数所在的文件,函数会挂载到window对象 require('./library/VoiceRecordingHelper'); test('uploadVoiceRecordingToBucket 应正确完成上传', async () => { // Mock函数依赖的全局API(比如fetch、Blob等) global.fetch = jest.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve({ uploadId: 'test-123' }) }); // 调用全局函数并传入测试参数 const uploadResult = await window.uploadVoiceRecordingToBucket({ recording: new Blob(['test-audio-data'], { type: 'audio/mpeg' }), targetBucket: 'test-storage-bucket' }); // 断言结果符合预期 expect(uploadResult.uploadId).toBe('test-123'); expect(fetch).toHaveBeenCalledTimes(1); });
方案二:手动模拟全局对象(无需jsdom)
如果测试不需要完整的浏览器环境,可以手动在Node环境中创建全局对象,让函数挂载到上面:
// 手动创建window全局对象(Node环境默认无此对象) global.window = {}; // 引入目标JS文件,函数会挂载到我们创建的window上 require('./library/VoiceRecordingHelper'); test('测试上传函数核心逻辑', async () => { // Mock依赖的全局方法 global.fetch = jest.fn().mockResolvedValue({ ok: true }); const result = await window.uploadVoiceRecordingToBucket(/* 传入测试参数 */); expect(result).toBeDefined(); });
注意事项
- 如果原JS文件依赖其他全局变量(比如
navigator、document),需要在测试中提前mock这些变量,避免执行报错。 - 全程不要修改原JS文件的导出逻辑,确保和fdk框架的兼容性。
内容的提问来源于stack exchange,提问作者DJRfume
相关产品推荐
相关产品推荐

