使用Jest测试带回调的异步JSON读取函数遇超时错误求助
解决Jest异步测试超时问题:你的JSON读取函数和Mock都有问题
我来帮你排查这个超时问题,根源其实有两个:待测试函数本身的逻辑错误,以及fs模块的Mock不符合异步回调规范。
问题1:待测试函数jsonReader的逻辑错误
看你的jsonReader函数,当JSON.parse成功后,你直接return object,但完全没有调用传入的cb回调函数!这就导致测试里的callback永远不会执行,done()自然也不会被触发,Jest一直在等回调,最后超时。
修复后的jsonReader应该是这样的(同时遵循Node.js标准回调模式:cb(err, result)):
function jsonReader(filePath, cb) { fs.readFile(filePath, (err, fileData) => { if (err) { return cb && cb(err); } try { const object = JSON.parse(fileData); // 成功时调用回调,传递null(无错误)和解析后的对象 return cb && cb(null, object); } catch (err) { return cb && cb(err); } }); } module.exports = jsonReader;
问题2:fs模块的Mock不符合异步回调格式
你现在Mock的readFile是直接返回值,但原fs.readFile是异步函数,它的第二个参数是回调函数,需要你手动调用这个回调来模拟异步传递数据或错误的过程。
修复后的Mock应该是这样的:
jest.mock('fs', () => { const MOCK_FILE_INFO = { 'test.json': JSON.stringify({ name: 'myname' }) }; return { readFile: (fpath, cb) => { // 用process.nextTick模拟异步行为,符合Node.js异步API的执行时机 process.nextTick(() => { if (fpath in MOCK_FILE_INFO) { // 成功场景:回调第一个参数为null,第二个为文件内容 cb(null, MOCK_FILE_INFO[fpath]); } else { // 模拟文件不存在的错误场景 cb(new Error('File not found')); } }); } }; });
修复后的完整测试代码
同时,测试里的回调要对应修改,接收错误和结果两个参数:
const jsonReader = require('../ReadJson'); jest.mock('fs', () => { const MOCK_FILE_INFO = { 'test.json': JSON.stringify({ name: 'myname' }) }; return { readFile: (fpath, cb) => { process.nextTick(() => { if (fpath in MOCK_FILE_INFO) { cb(null, MOCK_FILE_INFO[fpath]); } else { cb(new Error('File not found')); } }); } }; }); test('Test successful JSON file reading', (done) => { function callback(err, data) { // 先断言没有错误 expect(err).toBeNull(); expect(data.name).toBe('myname'); done(); } jsonReader('test.json', callback); }); // 额外增加错误场景的测试,覆盖更多逻辑 test('Test failed JSON file reading (file not exists)', (done) => { function callback(err) { expect(err).toBeInstanceOf(Error); expect(err.message).toBe('File not found'); done(); } jsonReader('nonexist.json', callback); });
这样修改后,你的测试应该就能正常通过,不会再出现超时问题了。
内容的提问来源于stack exchange,提问作者Dragoş Neagoe
相关产品推荐
相关产品推荐

