开玩笑测试中 UnhandledPromiseRejectionWarning 的含义是啥?

Posted

技术标签:

【中文标题】开玩笑测试中 UnhandledPromiseRejectionWarning 的含义是啥?【英文标题】:What is the meaning of UnhandledPromiseRejectionWarning in jest tests?开玩笑测试中 UnhandledPromiseRejectionWarning 的含义是什么? 【发布时间】:2019-10-10 23:28:09 【问题描述】:

ant 测试以下模块index.ts

async function theFunctionFail() 
  return await fail();


async function theFunctionSucceed() 
  return await succeed();


async function fail() 
  throw new Error();


async function succeed() 
  return "a";


export  theFunctionFail, theFunctionSucceed ;

使用测试index.test.ts

import  theFunctionFail, theFunctionSucceed  from "../index";

it('theFunctionFail', () => 
  expect(theFunctionFail()).rejects;
);

输出中的UnhandledPromiseRejectionWarning 是什么

(node:10515) UnhandledPromiseRejectionWarning: Error
(node:10515) 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(). (rejection id: 2)
(node:10515) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
 PASS  src/__tests__/index.test.ts
  ✓ theFunctionFail (6ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.806s
Ran all test suites.

参考?将 expect(theFunctionFail()).rejects 包装在 try-catch(err) 块中并不能避免我认为值得修复的警告。

为什么测试没有失败?/我怎样才能让测试失败?如果我的测试发现了一个严重的缺陷,我的理解应该不会成功。

我正在使用带有react-scripts 的 Typescript 和 Jest 24.7.1。

【问题讨论】:

【参考方案1】:

此警告指的是测试中发生了未处理的错误。真正的问题是你的测试没有测试任何东西——有一个没有匹配器的expect。应该是这样的:

return expect(theFunctionFail()).rejects.toEqual(new Error());

查看 .rejects 的 Jest 文档:https://jestjs.io/docs/en/tutorial-async#rejects

注意:也可以使用try/catch,但您必须像这样使用await

it('theFunctionFail', async () => 
  expect.assertions(1);
  try 
    await theFunctionFail();
   catch (err) 
    expect(err).toEqual(new Error());
  
);

或者返回异步函数并捕获错误(确保你返回函数):

it('theFunctionFail', () => 
  expect.assertions(1);
  return theFunctionFail().catch(err => 
    expect(err).toEqual(new Error());
  );
);

expect.assertions(number) 是确保在测试异步行为时调用所有 expects 的好方法。

此外,如果您添加错误消息,例如new Error('oh no!'),你肯定会知道你捕捉到了正确的错误,并且会让调试变得更容易。

【讨论】:

有没有办法更容易找到有问题的测试?我可以做一个临时的猴子补丁吗?对于这个项目,我有超过 1000 个,并且错误与输出中显示的位置不一致。 听起来您的问题可能出在您的代码中,而不是您的测试中。我会确保你的代码没有任何没有.catch 的承诺,或者try/catch 之外的任何awaits 对。如果不煞费苦心地单独运行每个测试,我只是不知道如何在代码中找到它。 嗨,想知道您是否找到了识别违规测试的方法?或者在你当地的笑话中重现这个?我们的笑话只在我们的 CI 管道中退出,在本地一切似乎都很好【参考方案2】:

在控制台中不产生 UnhandledPromiseRejectionWarning 的最干净的解决方案是使用 jest 的 expect.toThrow() 函数。

import  theFunctionFail, theFunctionSucceed  from "../index";

it('theFunctionFail', () => 
  expect(theFunctionFail()).rejects.toThrow();
);

您可以再次尝试匹配特定错误。例如。如果:

async function fail() 
  throw new Error('Something failed');

那么,你会测试:

it('theFunctionFail', () => 
  expect(theFunctionFail()).rejects.toThrow(Error('Something failed'));
);

【讨论】:

以上是关于开玩笑测试中 UnhandledPromiseRejectionWarning 的含义是啥?的主要内容,如果未能解决你的问题,请参考以下文章

ReferenceError:在开玩笑测试中没有定义 React

调度程序没有在开玩笑的单元测试中注册回调

开玩笑:测试不能在 setImmediate 或 process.nextTick 回调中失败

开玩笑测试:在打字稿组件导入中找不到模块

TypeError:state.customerComplaints.add 不是开玩笑单元测试中的函数

createWriteStream 的 ('error') 上的开玩笑单元测试