如何使用jest测试unhandledRejection/uncaughtException处理程序

Luk*_*kas 6 javascript unit-testing jestjs

我有unhandledRejections和uncaughtExceptions的处理程序:

bin.js

['unhandledRejection', 'uncaughtException'].forEach(event => {
  process.on(event, err => logger.error(err));
});
Run Code Online (Sandbox Code Playgroud)

现在我想测试它们jest:

bin.test.js

const bin = require('../bin');

test('catches unhandled rejections', async () => {
  const error = new Error('mock error');
  await Promise.reject(error);
  expect(logger.error).toHaveBeenCalledWith(error);
});

test('catches uncaught exceptions', () => {
  const error = new Error('mock error');
  throw error;
  expect(logger.error).toHaveBeenCalledWith(error);
});
Run Code Online (Sandbox Code Playgroud)

jest只是告诉我测试中有错误:

●捕获未处理的拒绝

mock error

   8 | // https://github.com/facebook/jest/issues/5620
   9 | test('catches unhandled rejections', async () => {
> 10 |   const error = new Error('mock error');
     |                 ^
  11 |   await Promise.reject(error);
  12 |   expect(logger.error).toHaveBeenCalledWith(error);
  13 | });

  at Object.<anonymous>.test (test/bin.test.js:10:17)
Run Code Online (Sandbox Code Playgroud)

●捕获未捕获的异常

mock error

  14 |
  15 | test('catches uncaught exceptions', () => {
> 16 |   const error = new Error('mock error');
     |                 ^
  17 |   throw error;
  18 |   expect(logger.error).toHaveBeenCalledWith(error);
  19 | });

  at Object.<anonymous>.test (test/bin.test.js:16:17)
Run Code Online (Sandbox Code Playgroud)

有没有办法测试这个?

这可能是相关的:https://github.com/facebook/jest/issues/5620

sli*_*wp2 5

我的测试策略是使用jest.spyOn(object, methodName)安装间谍process.on()logger.error方法。这样做之后,这些方法就没有副作用了。然后,您可以在隔离环境中测试代码逻辑。

\n

除此之外,还有以下几点需要注意:

\n
    \n
  • 您应该在语句之前监视函数require(\'./bin\')。因为当你加载bin.js模块时,代码就会被执行。
  • \n
  • 您应该在挂钩中使用jest.resetModules()beforeEach来重置模块注册表 - 所有必需模块的缓存。为什么?因为require()缓存了它的结果。因此,第一次需要模块时,就会运行其初始化代码。之后,缓存只是返回 的值,module.exports而不再运行初始化代码。但是我们有两个测试用例,我们希望模块范围内的代码执行两次。
  • \n
\n

现在,这是一个例子:

\n

bin.js:

\n
const logger = require(\'./logger\');\n\n[\'unhandledRejection\', \'uncaughtException\'].forEach((event) => {\n  process.on(event, (err) => logger.error(err));\n});\n
Run Code Online (Sandbox Code Playgroud)\n

logger.js:

\n
const logger = console;\n\nmodule.exports = logger;\n
Run Code Online (Sandbox Code Playgroud)\n

bin.test.js:

\n
const logger = require(\'./logger\');\n\ndescribe(\'52493145\', () => {\n  beforeEach(() => {\n    jest.resetModules();\n  });\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n  test(\'catches unhandled rejections\', () => {\n    const error = new Error(\'mock error\');\n    jest.spyOn(process, \'on\').mockImplementation((event, handler) => {\n      if (event === \'unhandledRejection\') {\n        handler(error);\n      }\n    });\n    jest.spyOn(logger, \'error\').mockReturnValueOnce();\n    require(\'./bin\');\n    expect(process.on).toBeCalledWith(\'unhandledRejection\', expect.any(Function));\n    expect(logger.error).toHaveBeenCalledWith(error);\n  });\n\n  test(\'catches uncaught exceptions\', () => {\n    const error = new Error(\'mock error\');\n    jest.spyOn(process, \'on\').mockImplementation((event, handler) => {\n      if (event === \'uncaughtException\') {\n        handler(error);\n      }\n    });\n    jest.spyOn(logger, \'error\').mockReturnValueOnce();\n    require(\'./bin\');\n    expect(process.on).toBeCalledWith(\'uncaughtException\', expect.any(Function));\n    expect(logger.error).toHaveBeenCalledWith(error);\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

单元测试结果:

\n
 PASS  examples/52493145/bin.test.js\n  52493145\n    \xe2\x9c\x93 catches unhandled rejections (5 ms)\n    \xe2\x9c\x93 catches uncaught exceptions (1 ms)\n\n-----------|---------|----------|---------|---------|-------------------\nFile       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n-----------|---------|----------|---------|---------|-------------------\nAll files  |     100 |      100 |     100 |     100 |                   \n bin.js    |     100 |      100 |     100 |     100 |                   \n logger.js |     100 |      100 |     100 |     100 |                   \n-----------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests:       2 passed, 2 total\nSnapshots:   0 total\nTime:        2.73 s, estimated 4 s\n
Run Code Online (Sandbox Code Playgroud)\n

源代码:https://github.com/mrdulin/jest-v26-codelab/tree/main/examples/52493145

\n


小智 -3

把它放在 try catch 中会有所帮助:

const error = new Error('模拟错误');

尝试 {

await Promise.reject(error);
Run Code Online (Sandbox Code Playgroud)

} 捕获(错误){

   expect(logger.error).toHaveBeenCalledWith(error);
Run Code Online (Sandbox Code Playgroud)

}