我在这个问题上纠缠了3个小时。我没有找到一个解决方案,如何测试以下代码中的if(err)分支:
function createFile(data){
return new Promise(function(resolve, reject) {
try {
if(data === null || data === undefined){
throw new Error(errorMessages.noDataDefined);
}
let internalJobId = uuid.v4();
let fileName = 'project_name' + internalJobId + '.xml';
fs.writeFile(config.tmpPath + fileName, data, function (err) {
if (err){
throw new Error(err.toString());
} else {
resolve(fileName);
}
});
} catch (error) {
return reject(error);
}
});
}
此测试通过,但不调用if(err){ throw new Error(err.toString())}
我必须找到一个解决方案,回调如何返回错误,但我没有得到正确的解决方案。
test('Error', () => {
jest.mock('fs', () => ({
writeFile: jest.fn((path, data, callback) => callback(Error('some error')))
}));
return expect(createFile('Does not matter')).rejects.toThrow('some error');
});
但是有了这个测试,甚至没有一个拒绝,所以从来没有抛出一个错误。我将不胜感激,如果有人能帮助我在那里。
3条答案
按热度按时间j2cgzkjk1#
这里 有 两 个 问题 , 一 个 是
fs.writeFile
没有 被 正确 地 模拟 , 另 一 个 是createFile
没有 正确 地 处理 错误 , 不能 达到 预期 。jest.mock
会 影响 那些 还 没有 被 导入 并 被 提升 到 块 顶部 的 模块 ( 或者 在 顶层 使用 时 , 提升 到 导入 模块 之上 ) 。 如果 使用fs
的 模块 已经 被 导入 , 则 它 不会 影响fs
。 由于fs
函数 通常 与 它们 的 命名 空间 一起 使用 , 因此 它们 也 可以 被 模拟 为 方法 。它 应该 是 :
中 的 每 一 个
或者 :
格式
并 被 Assert 以 使 测试 更 具体 :
格式
Promise 构造 函数 不 需要
try..catch
, 因为 它 已经 捕获 了 内部 的 所有 * synchronous * 错误 , 无法 从 回调 中 捕获 异步 错误 。 对于 需要 拒绝 Promise 的 地方 , 为了 一致 性 ,reject
可以 被 首选 。在
fs.writeFile
回调 内 抛出 错误 是 一 个 错误 , 并 导致 待定 承诺 。 它 没有 机会 拒绝 承诺 , 也 没有 机会 在 回调 外 被try..catch
捕获 , 并 导致 未 捕获 的 错误 。它 应该 是 :
格式
为了 使 嵌套 最 小 化 , 可以 将 不 需要 承诺 的 部分 移 到 构造 函数 之外 , 函数 为
async
:格式
还有 可能 不 需要 承诺 的
fs.promises
API 。另 请 注意 ,
new Error(err.toString())
可能 是 不 必要 的 , 并 会 导致 未 预期 的 错误 消息 , 因此 宣告 失败 。 可以 使用err
来 拒绝 此 承诺 。 如果 目的 是 移除 不 必要 的 错误 信息 或 变更 错误 堆栈 , 则 应该 使用new Error(err.message)
。col17t5w2#
解决方案是:
感谢埃斯图斯·弗拉斯克!
ykejflvf3#
下面的三行代码为我完成了这项工作: