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

标签 javascript node.js unit-testing jestjs

我有 unhandledRejection 的处理程序s 和 uncaughtException年代:

bin.js

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

现在我想用 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);
});

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

● catches unhandled rejections

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)

● catches uncaught exceptions

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)


有没有办法测试这个?

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

最佳答案

我的测试策略是将 spy 安装到 process.on()logger.error使用 jest.spyOn(object, methodName) 的方法.这样做之后,这些方法就没有副作用了。然后,您可以在隔离环境中测试您的代码逻辑。
除此之外,还有几点需要注意:

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

  • 现在,这里是示例:bin.js :
    const logger = require('./logger');
    
    ['unhandledRejection', 'uncaughtException'].forEach((event) => {
      process.on(event, (err) => logger.error(err));
    });
    
    logger.js :
    const logger = console;
    
    module.exports = logger;
    
    bin.test.js :
    const logger = require('./logger');
    
    describe('52493145', () => {
      beforeEach(() => {
        jest.resetModules();
      });
      afterEach(() => {
        jest.restoreAllMocks();
      });
      test('catches unhandled rejections', () => {
        const error = new Error('mock error');
        jest.spyOn(process, 'on').mockImplementation((event, handler) => {
          if (event === 'unhandledRejection') {
            handler(error);
          }
        });
        jest.spyOn(logger, 'error').mockReturnValueOnce();
        require('./bin');
        expect(process.on).toBeCalledWith('unhandledRejection', expect.any(Function));
        expect(logger.error).toHaveBeenCalledWith(error);
      });
    
      test('catches uncaught exceptions', () => {
        const error = new Error('mock error');
        jest.spyOn(process, 'on').mockImplementation((event, handler) => {
          if (event === 'uncaughtException') {
            handler(error);
          }
        });
        jest.spyOn(logger, 'error').mockReturnValueOnce();
        require('./bin');
        expect(process.on).toBeCalledWith('uncaughtException', expect.any(Function));
        expect(logger.error).toHaveBeenCalledWith(error);
      });
    });
    
    单元测试结果:
     PASS  examples/52493145/bin.test.js
      52493145
        ✓ catches unhandled rejections (5 ms)
        ✓ catches uncaught exceptions (1 ms)
    
    -----------|---------|----------|---------|---------|-------------------
    File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    -----------|---------|----------|---------|---------|-------------------
    All files  |     100 |      100 |     100 |     100 |                   
     bin.js    |     100 |      100 |     100 |     100 |                   
     logger.js |     100 |      100 |     100 |     100 |                   
    -----------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       2 passed, 2 total
    Snapshots:   0 total
    Time:        2.73 s, estimated 4 s
    
    源代码:https://github.com/mrdulin/jest-v26-codelab/tree/main/examples/52493145

    关于javascript - 如何用 jest 测试 unhandledRejection/uncaughtException 处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52493145/

    相关文章:

    javascript - 使用 lodash 对数组对象与日期进行排序

    node.js - 获取 MongoDB 文档中嵌入集合的计数

    JavaScript 动态对象键 ejs

    node.js - 无法在 Windows 上使用 fs 写入文件

    c# - "Short circuiting"最小起订量无效方法?

    unit-testing - 如何在自定义文件夹中使用 go test 生成多个包的覆盖率?

    python - 有没有开源工具可以自动为遗留代码生成测试用例?

    javascript - 提交表单后禁用重定向

    javascript - 让搜索框在输入时获取页面

    javascript - 如何使固定元素保持相对于当前顶部滚动位置?