Jest.js无法模拟嵌套本地函数的技术问询
解决Jest手动模拟本地嵌套函数不生效的问题
这个问题我之前也踩过坑,核心原因是模块导入顺序错误——Jest会优先处理所有顶层的import语句,你在模拟模块之后才导入依赖它的getNewJob,导致getNewJob已经绑定了原始的getNextId函数,后续的模拟根本覆盖不到。
正确解决方案:用jest.mock提前模拟模块
jest.mock会被Jest自动提升到所有代码执行之前,确保目标模块被导入时拿到的是模拟版本,而不是原始模块。
基础版测试代码
// 第一步:先模拟db模块,必须放在所有import之前 jest.mock('../../db', () => ({ getNextId: jest.fn(() => Promise.resolve(0)) // 直接指定模拟返回值 })); // 第二步:导入依赖模块,此时它们会使用模拟后的getNextId import { getNewJob, Job } from '../../app/job'; import { someUtilMethod } from '../../app/util'; describe('Job creation tests', () => { it('should generate a Job with mocked id', async () => { // 调用目标函数(现在会用模拟的getNextId) const job = await getNewJob(); const testVal = someUtilMethod(job); // 执行断言 expect(job.id).toBe(0); // 这里添加你对someUtilMethod结果的断言,比如: // expect(testVal).toBe('expected-value'); }); });
动态修改模拟返回值(多测试用例场景)
如果需要在不同测试用例中返回不同的id,可以通过jest.Mock类型断言来修改模拟函数的返回值:
// 仍然先提前模拟模块 jest.mock('../../db', () => ({ getNextId: jest.fn() // 先初始化一个空的mock函数 })); import { getNextId } from '../../db'; import { getNewJob } from '../../app/job'; describe('Job creation tests', () => { it('should use id 0 in first case', async () => { // 设置当前用例的返回值 (getNextId as jest.Mock).mockResolvedValue(0); const job = await getNewJob(); expect(job.id).toBe(0); }); it('should use id 100 in second case', async () => { // 覆盖为新的返回值 (getNextId as jest.Mock).mockResolvedValue(100); const job = await getNewJob(); expect(job.id).toBe(100); }); });
为什么你原来的方法无效?
你用jest.createMockFromModule创建的模拟模块只是一个普通对象,并没有替换Jest内部的模块缓存。当你后续导入../../app/job时,它会从缓存中加载原始的../../db模块,绑定真实的getNextId函数,所以你的模拟代码根本没被调用到。
只有jest.mock能真正覆盖Jest的模块缓存,确保所有依赖该模块的代码都使用模拟版本。
内容的提问来源于stack exchange,提问作者Matt Weaver
相关产品推荐
相关产品推荐

