首页 > 解决方案 > 当发生未捕获的 Promise 拒绝时,我如何在 Jest 中通过测试失败?

问题描述

我正在为我正在使用 Jest 的 Node 项目添加测试覆盖率。我正在测试的代码在承诺中引发错误,导致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 记录抛出的错误并失败测试,​​但不会崩溃。(即测试观察者不断观察和运行测试)

标签: javascriptnode.jsunit-testingjestjs

解决方案


我处理这个问题的方式与我编写函数的方式密切相关——基本上,任何使用 Promise 的函数都应该返回一个 Promise。这允许调用该函数的任何代码以它认为合适的任何方式处理捕获错误。请注意,这是我的方法,我不会声称这是做事的唯一方法。

例如......想象一下我正在测试这个功能:

const myFunction = () => {
    return doSomethingWithAPromise()
        .then(() => {
            console.log('no problems!');
            return true;
        });
};

测试将如下所示:

describe('...', () => {
    it('...', () => {
        return myFunction()
            .then((value) => {
                expect(value).toBe(true);
            });
    });
});

效果很好。现在如果 promise 被拒绝会发生什么?在我的测试中,被拒绝的承诺被传回给 Jest(因为我正在返回我的函数调用的结果)并且 Jest 可以报告它。

相反,如果您的函数没有返回承诺,您可能必须执行以下操作:

const myOtherFunction = () => {
    doSomethingWithAPromise()
        .then(() => {
            console.log('no problems!');
            return true;
        })
        .catch((err) => {
             // throw the caught error here
             throw err;
        });
};

与上面的示例不同,Jest 没有(直接)方法来处理被拒绝的承诺,因为您没有将承诺传回给 Jest。避免这种情况的一种方法可能是确保catch函数中有一个来捕获并抛出错误,但我还没有尝试过,我不确定它是否会更可靠。


推荐阅读