我在这个话题上坚持了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){抛出新错误(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');
});
但是通过此测试,甚至没有拒绝,因此永远不会抛出错误。如果有人可以帮助我,我将不胜感激。
答案 0 :(得分:1)
这里有两个问题。一种是fs.writeFile
未被正确模拟。另一个是createFile
无法正确处理错误,无法满足期望。
jest.mock
影响尚未导入并提升到块顶部(或在顶层使用时高于导入)的模块。如果已经导入了使用fs
的模块,则它不会影响fs
。由于// at top level
import fs from 'fs';
jest.mock('fs', ...);
...
函数通常与其名称空间一起使用,因此也可以将它们模拟为方法。
应该是:
// inside test
jest.spyOn(fs, 'writeFile').mockImplementation(...);
...
或者:
expect(fs.writeFile).toBeCalledTimes(1);
expect(fs.writeFile).toBeCalledWith(...);
return expect(createFile('Does not matter'))...
并断言要使测试更具体:
try..catch
Promise构造函数不需要reject
,因为它已经捕获了其中的所有 synchronous 错误,并且无法捕获回调中的异步错误。对于需要兑现承诺的地方,fs.writeFile
可以保持一致性。
在try..catch
回调中引发错误是一个错误,并导致未完成的Promise。它没有机会拒绝诺言,也没有机会在回调之外被function createFile(data){
return new Promise(function(resolve, reject) {
if(data === null || data === undefined){
reject(new Error(errorMessages.noDataDefined));
}
let internalJobId = uuid.v4();
let fileName = 'project_name' + internalJobId + '.xml';
fs.writeFile(config.tmpPath + fileName, data, function (err) {
if (err){
reject(new Error(err.toString()); // reject(err) ?
} else {
resolve(fileName);
}
});
});
}
捕获,并导致未捕获的错误。
应该是:
async
为了使嵌套最少,可以将不需要多余的部分移到构造函数之外,并使用async function createFile(data){
if(data === null || data === undefined){
throw new Error(errorMessages.noDataDefined);
}
return new Promise(function(resolve, reject) {
let internalJobId = uuid.v4();
...
函数:
new Error(err.toString())
也可能不需要fs.promises
API。
还要注意,err
可能不必要,并且会导致意外的错误消息,从而使声明失败。可以用new Error(err.message)
拒绝诺言。如果要删除不必要的错误信息或更改错误堆栈,则应为{{1}}。
答案 1 :(得分:0)
解决方案是:
jest.spyOn(fs, 'writeFile').mockImplementation((f, d, callback) => {
callback('some error');
});
感谢Estus Flask!