如何为依赖外部函数的.mjs文件编写Jest测试?
如何测试依赖全局对象的ESM函数(无需修改原代码)
看起来你在给大型项目里的.mjs函数写Jest测试时卡壳了——原函数依赖全局的VideoList.GetCurrentVideo(),但测试环境里没有这个对象,导致返回undefined,还不能改原代码?没问题,我们可以通过Mock全局依赖的方式搞定,完全不用动项目里的原有代码,下面是具体方案:
方案1:直接Mock全局的VideoList对象
在测试文件里,我们可以在测试前后创建并清理全局的VideoList对象,同时Mock它的方法来模拟返回值:
// 替换成你实际的模块导入路径 import { getCurrentVideo } from '../path-to-your-module.mjs'; describe('getCurrentVideo', () => { // 每个测试前初始化全局Mock对象 beforeEach(() => { global.VideoList = { GetCurrentVideo: jest.fn() // 把这个方法变成Jest的Mock函数 }; }); // 每个测试后清理,避免影响其他测试用例 afterEach(() => { delete global.VideoList; jest.clearAllMocks(); }); test('返回拼接后的正确视频字符串', () => { // 模拟GetCurrentVideo的返回值 const mockVideo = 'my-test-video-123'; global.VideoList.GetCurrentVideo.mockReturnValue(mockVideo); const result = getCurrentVideo(); // 验证返回结果是否符合预期 expect(result).toBe(`This is the video:${mockVideo}`); // 还能验证原函数确实调用了这个方法 expect(global.VideoList.GetCurrentVideo).toHaveBeenCalledTimes(1); }); });
方案2:如果VideoList是可导入模块,用jest.mockMock整个模块
如果VideoList本身是一个项目里的模块(而不是挂在全局的对象),那我们可以直接用Jest的jest.mock来Mock整个模块:
假设VideoList的文件路径是./VideoList.mjs,原模块代码大概是这样:
// ./VideoList.mjs export function GetCurrentVideo() { // 项目里的原实现 }
那测试文件可以这么写:
import { getCurrentVideo } from '../path-to-your-module.mjs'; import * as VideoList from '../VideoList.mjs'; // Mock整个VideoList模块,替换成我们的Mock函数 jest.mock('../VideoList.mjs', () => ({ GetCurrentVideo: jest.fn() })); describe('getCurrentVideo', () => { test('返回正确的视频拼接字符串', () => { const mockVideo = 'another-test-video-456'; VideoList.GetCurrentVideo.mockReturnValue(mockVideo); const result = getCurrentVideo(); expect(result).toBe(`This is the video:${mockVideo}`); expect(VideoList.GetCurrentVideo).toHaveBeenCalledTimes(1); }); });
注意事项
- 测试独立性:一定要在
afterEach里清理全局对象或者重置Mock函数,不然一个测试的Mock会影响其他测试的结果。 - ESM配置:Jest处理ESM需要确保你的
jest.config.js里有正确配置,比如设置extensionsToTreatAsEsm: ['.mjs'],或者运行测试时加上--experimental-vm-modules标志(具体看Jest版本)。 - 无需修改原代码:这种Mock方式完全是在测试环境里做的,不会碰项目里的任何原有代码,完美符合你不能改原函数的需求。
内容的提问来源于stack exchange,提问作者Rowin_nb2
相关产品推荐
相关产品推荐

