我正在努力将测试覆盖率添加到我正在使用Jest的Node项目中。我正在测试的代码是在promises中抛出错误,导致UnhandledPromiseRejectionWarning
消息被记录到控制台。
在编写测试时,我可以非常轻松地识别这些问题并解决它们,但这些警告实际上并没有导致Jest将测试标记为失败,因此我们的CI将无法捕获它。我四处寻找任何建议,但没有找到太多建议。
我确实在Node的文档中发现你可以捕获这些警告并处理它们......
process.on('unhandledRejection', (error) => {
throw error; // Or whatever you like...
});
因此,将此代码添加到我的测试用例中似乎非常简单。毕竟,测试中抛出的Error
会导致测试失败......
describe('...', () => {
it('...', () => {
process.on('uncaughtRejection', (error) => {
throw error;
});
// the rest of my test goes here
});
});
不幸的是,我看到的行为是错误 被抛出,但是Jest没有捕获它并且未通过测试。相反,Jest崩溃时出现此错误,测试不会继续运行。这不太可取,似乎是不正确的行为。
在uncaughtRejection
处理程序之外抛出错误按预期工作:Jest记录抛出的错误并使测试失败,但不会崩溃。 (即测试观察者继续观察并运行测试)
答案 0 :(得分:1)
我接近这一点的方式与我编写函数的方式密切相关 - 基本上,任何使用promises的函数都应该返回一个promise。这允许任何函数的代码调用以任何它认为合适的方式处理捕获错误。请注意,这是我的方法,我不会声称这是唯一的做法。
例如......想象一下,我正在测试这个功能:
const myFunction = () => {
return doSomethingWithAPromise()
.then(() => {
console.log('no problems!');
return true;
});
};
测试看起来像这样:
describe('...', () => {
it('...', () => {
return myFunction()
.then((value) => {
expect(value).toBe(true);
});
});
});
哪个效果很好。现在如果承诺被拒绝会怎样?在我的测试中,被拒绝的承诺被传递回Jest(因为我正在返回我的函数调用的结果)并且Jest可以报告它。
相反,如果您的函数没有返回承诺,则可能需要执行以下操作:
const myOtherFunction = () => {
doSomethingWithAPromise()
.then(() => {
console.log('no problems!');
return true;
})
.catch((err) => {
// throw the caught error here
throw err;
});
};
与上面的示例不同,Jest没有(直接)方式处理被拒绝的承诺,因为您没有将承诺传递给Jest。避免此的一种方法可能是确保函数中有catch
来捕获&抛出错误,但我没有尝试过,我不确定它是否会更可靠。
答案 1 :(得分:1)
模块:
export function myPromise() {
return new Promise((resolve, reject) => {
const error = new Error('error test');
reject(error);
});
}
测试:
import { myPromise } from './module';
it('should reject the promise', () => {
expect.assertions(1);
const expectedError = new Error('error test');
myPromise().catch((error) => {
expect(error).toBe(expectedError);
});
答案 2 :(得分:0)
从节点文档site中我们可以看到The process object is an instance of EventEmitter
。
使用process
中的emit函数,可以在需要时以编程方式触发类似uncaughtRejection
和uncaughtException
的错误。
it("should log the error", () => {
process.emit("unhandledRejection");
...
const loggerInfo = jest.spyOn(logger, "info");
expect(loggerInfo).toHaveBeenCalled();
});
答案 3 :(得分:0)
在Jest's setupFiles
中包括以下内容:
if (!process.env.LISTENING_TO_UNHANDLED_REJECTION) {
process.on('unhandledRejection', reason => {
throw reason
})
// Avoid memory leak by adding too many listeners
process.env.LISTENING_TO_UNHANDLED_REJECTION = true
}
由stipsan中的https://github.com/facebook/jest/issues/3251#issuecomment-299183885提供。
答案 4 :(得分:-1)
不确定这是否有帮助,但您也可以声明承诺拒绝
<强> index.js 强>
module.exports = () => {
return Promise.reject('it didnt work');
}
<强> index.spec.js 强>
const thing = require('../src/index');
describe('rejected promise', () => {
it('should reject with a reason', ()=> {
return expect(thing()).rejects.toEqual('it didnt work');
});
});