Jest测试加载前次测试残留模块 动态require JSON出现undefined报错如何解决
问题根源
- 第一个测试用例未给
AddCardForm传入langSelected参数,导致langSelected值为undefined,动态拼接出的导入路径为../langJsons/undefined.json,本身不存在该文件会触发报错 jest.resetModules()仅对执行重置操作后新导入的模块生效,你测试文件顶部已经提前静态导入了AddCardForm组件,组件内部的require缓存不会被resetModules清理,因此前一次测试的导入错误会残留到后续用例- 切换为
fetch后报错是因为Jest运行在Node.js环境,不存在浏览器的网络请求环境,相对路径请求会默认指向127.0.0.1:80,本地没有对应服务自然会抛出连接拒绝错误
可行解决方案
- 方案1:给组件逻辑加兜底(最推荐,属于业务代码健壮性优化)
修改AddCardForm的useEffect逻辑,参数校验不通过时不执行资源加载:
useEffect(() => { async function getGrammarInputNames(lang, grammar) { // 加参数校验 if (!lang || !grammar) return const file = require(`../langJsons/${lang}.json`); const obj = file[`add${grammar}`]['translation'][0][`grammar${grammar}`]; setGrammarInputNames(Object.values(obj)); } getGrammarInputNames(langSelected, grammarSelected); }, [langSelected, grammarSelected]);
修改后第一个测试用例不会触发无效的JSON加载,自然不会有报错残留。
- 方案2:动态导入组件配合模块重置
如果不需要修改业务代码,可以调整测试用例的导入逻辑,每次测试前重新导入组件:
// 删除测试文件顶部的静态import AddCardForm语句 beforeEach(() => { jest.resetModules(); // 每次动态导入最新的组件模块,替换为你的组件实际路径 AddCardForm = require('./AddCardForm').default; });
- 方案3:Mock动态JSON导入
直接在测试文件顶部Mock所有需要用到的JSON模块,避免真实路径查找:
// Mock不存在的undefined.json jest.mock('../langJsons/undefined.json', () => ({}), { virtual: true }); // Mock实际业务用到的Norwegian.json,填入你需要的测试返回数据 jest.mock('../langJsons/Norwegian.json', () => ({ addNoun: { translation: [ { grammarNoun: { testKey: 'testValue' } } ] } }));
- 方案4:修复fetch调用的测试适配
如果要保留fetch加载方式,需要在测试中全局Mock fetch方法:
beforeEach(() => { global.fetch = jest.fn((url) => { // 匹配挪威语JSON请求返回对应测试数据 if (url.includes('Norwegian.json')) { return Promise.resolve({ ok: true, json: () => Promise.resolve({ addNoun: { translation: [{ grammarNoun: {} }] } }) }) } // 匹配undefined的请求返回失败 return Promise.reject(new Error('File not found')) }) }) afterEach(() => { jest.clearAllMocks() })
内容的提问来源于stack exchange,提问作者Kyatt
相关产品推荐
相关产品推荐

