使用Jest测试TypeScript代码时遭遇ReferenceError报错求助
问题分析
报错ReferenceError: Cannot access 'getDeciderMock' before initialization的核心原因是Jest会将jest.mock调用提升到文件最顶部执行,而代码中getDeciderMock是在jest.mock之后定义的,当jest.mock的工厂函数执行时,getDeciderMock还未完成初始化,因此触发该错误。
另外原测试代码存在一个语法错误:jest.mock的工厂函数末尾缺少闭合括号),也需要一并修正。
解决方案
提供两种可行的修复方式:
方案一:在jest.mock内部直接创建Mock,通过类型断言获取控制
将getDecider的Mock直接定义在jest.mock的工厂函数中,后续通过类型断言把导入的getDecider转为jest.Mock类型,即可正常控制它的返回值:
import { Service } from './Service'; import { getDecider } from './decider'; // 直接在jest.mock内部创建getDecider的mock jest.mock('./decider', () => ({ getDecider: jest.fn(), })); // 类型断言将getDecider转为jest.Mock const getDeciderMock = getDecider as jest.Mock; const isBMock = jest.fn(); const deciderMock = { exp: { isB: isBMock, }, blah: 'test', }; describe('test', () => { beforeEach(() => { isBMock.mockReturnValue(true); getDeciderMock.mockReturnValue(deciderMock); }); it('should return b-url', () => { const result = Service.getUrl(); expect(result).toBe('b-url'); }); });
方案二:使用jest.doMock替代jest.mock(特殊场景适用)
jest.doMock不会被Jest自动提升,会按照代码书写顺序执行,确保getDeciderMock初始化后再被引用:
const isBMock = jest.fn(); const deciderMock = { exp: { isB: isBMock, }, blah: 'test', }; const getDeciderMock = jest.fn(); // 用jest.doMock替代jest.mock,避免自动提升 jest.doMock('./decider', () => ({ getDecider: getDeciderMock, })); describe('test', () => { beforeEach(() => { isBMock.mockReturnValue(true); getDeciderMock.mockReturnValue(deciderMock); }); it('should return b-url', async () => { // 动态导入Service,确保mock生效 const { Service } = await import('./Service'); const result = Service.getUrl(); expect(result).toBe('b-url'); }); });
额外注意事项
- 优先选择方案一,
jest.mock是Jest推荐的标准Mock方式,jest.doMock仅适合需要根据条件动态Mock的特殊场景。 - 确保所有
jest.mock类调用的语法完整,避免因括号遗漏等低级语法错误导致额外问题。
内容的提问来源于stack exchange,提问作者hendrixchord
相关产品推荐
相关产品推荐

