javascript - Jest test execution shows UnhandledPromiseRejectionWarning despite the test is working well
问题描述
I will try to describe the problem with the minimal reproduction code.
So I have a function with a dependency like this one:
import "./styles.css";
function thatRecivesInjectedDependency(aDependency) {
aDependency
.doSomethingAsync()
.then((result) => {
console.log("it happened");
})
.catch((error) => {
throw error;
});
}
export default thatRecivesInjectedDependency;
And I want to test it with a test double like this:
import sut from ".";
test("should throw an error if the the assets load went wrong", async () => {
const fakeDependency = {
doSomethingAsync: jest
.fn()
.mockImplementation(() => Promise.reject(new Error("ERROR!")))
};
sut(fakeDependency);
await expect(fakeDependency.doSomethingAsync).rejects.toThrowError(
new Error("ERROR!")
);
});
For some reason, is the only way I found to make the test work, it's not giving me false positive results, you can check it by changing the error text in the mockImplementation
or in the toThrowError
so it will fail, but still is showing up:
(node:46044) UnhandledPromiseRejectionWarning: Error: ERROR!
(node:46044) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 114)
Any clue that what it's happening and how can I resolve it? Did something wrong?
解决方案
This is a no-op:
.catch((error) => {
throw error;
});
catch
can be perceived by a developer as handled error but this one just rethrows it. If the intention is to allow a caller to handle the error, it can be omitted. If the intention is to suppress the error, it can be changed to catch(() => {})
but this may lead to other mistakes, as a caller cannot determine if there was an error while this may be important.
thatRecivesInjectedDependency
doesn't return a promise and there's loose promise chain. A caller is unable to chain it and wait for thatRecivesInjectedDependency
to finish. That catch
doesn't really handle errors makes it impossible to handle them in a caller.
It should be:
return aDependency
.doSomethingAsync()
.then((result) => {
console.log("it happened");
});
The test doesn't chain the result, this will result in unhandled rejection. Instead it tests itself because it asserts that mocked function rejects; this is already known because this is exactly that was written several lines above.
The coverage can be increased by asserting console.log
.
It should be:
jest.spyOn(console, 'log');
await expect(sut(fakeDependency)).rejects.toThrowError("ERROR!");
expect(console.log).not.toBeCalled();
Notice that toThrowError(new Error("ERROR!"))
is excessive because it checks either error constructor or message but not both.
推荐阅读
- c# - ZKteco SDK 打开/关闭特定门(门禁设备)
- jenkins - 未生成 newman htmlextra 报告
- node.js - res.end() 不是 nodejs 上的功能问题
- python-3.x - Python json.loads() 返回一个字符串而不是字典
- mysql - 如何连接到共享的 mysql 数据库来为 bi 供电
- python - 无法在 python 请求模块中获取 cookie
- python - 如何使用熊猫附加到csv文件两列的底行?
- flutter - 断言失败:第 258 行 pos 16:'child == null || indexOf(child) > index': 不正确
- reactjs - CreateBrowserHistory 未在页面刷新 Chrome 时保留历史状态
- flutter - Flutter:在屏幕上拖动小部件(不是拖放)