【问题标题】:Testing default error handler in an express application results in a timeout在快速应用程序中测试默认错误处理程序会导致超时
【发布时间】:2021-08-27 16:23:48
【问题描述】:

在测试快速应用程序的默认错误处理程序时,会导致超时。函数如下:

const createApp = (underlyingFunction) => {
  const app = express()
  app.get('/my-endpoint', async (req, res) => {
    await underlyingFunction()
    res.send({ success: true })
  })

  const errorHandler: ErrorRequestHandler = (error, req, res, next) => {
    console.error('Unhandled exception');
    console.error(error);
    console.error(error.stack);
    res.status(500).send({
      message: 'Oh dear',
    });
    // next()
  }

  app.use(errorHandler)
  return app;
}
  

测试如下:

  test('error should be handled and return 500', async () => {
    underlyingFunction.mockImplementation(() => {
      throw new Error('Something went wrong')
    })

    const app = createApp(underlyingFunction)
    const response = await request(app).get('/my-endpoint')

    expect(response.status).toBe(500)
  })

运行测试时,出现以下错误:

    thrown: "Exceeded timeout of 5000 ms for a test.
    Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

这可能是什么原因造成的?

【问题讨论】:

  • underlyingFunctioncreateApp 看起来像什么?创建一个最小的、可重现的示例
  • @slideshowp2 感谢您的反馈。我已经更新了问题。

标签: node.js express jestjs supertest ts-jest


【解决方案1】:

对于express V4,从Error Handling#Catching Errors 文档中,我们知道:

对于由路由处理程序和中间件调用的异步函数返回的错误,您必须将它们传递给 next() 函数,Express 将在该函数中捕获并处理它们。

虽然测试用例中mock的underlyingFunction是同步的,但是在路由中,async/await语法将这个路由处理函数转换成异步代码。

因此,您需要使用try...catch 语句来捕获underlyingFunction 函数引发的错误。并将error 传递给next 函数。 express 会将请求路由到带有 error 的错误处理程序中间件。

例如

app.ts:

import express from 'express';
import { ErrorRequestHandler } from 'express-serve-static-core';

export const createApp = (underlyingFunction) => {
  const app = express();

  app.get('/my-endpoint', async (req, res, next) => {
    try {
      await underlyingFunction();
      res.send({ success: true });
    } catch (error) {
      next(error);
    }
  });

  const errorHandler: ErrorRequestHandler = (error, req, res, next) => {
    console.error('Unhandled exception');
    res.status(500).send({ message: 'Oh dear' });
  };

  app.use(errorHandler);
  return app;
};

app.test.ts:

import request from 'supertest';
import { createApp } from './app';

describe('68923821', () => {
  test('error should be handled and return 500', async () => {
    const underlyingFunction = jest.fn().mockImplementation(() => {
      throw new Error('Something went wrong');
    });
    const app = createApp(underlyingFunction);
    const res = await request(app).get('/my-endpoint');
    expect(res.status).toEqual(500);
  });
});

测试结果:

 PASS  examples/68923821/app.test.ts (9.128 s)
  68923821
    ✓ error should be handled and return 500 (49 ms)

  console.error
    Unhandled exception

      15 | 
      16 |   const errorHandler: ErrorRequestHandler = (error, req, res, next) => {
    > 17 |     console.error('Unhandled exception');
         |             ^
      18 |     res.status(500).send({ message: 'Oh dear' });
      19 |   };
      20 | 

      at errorHandler (examples/68923821/app.ts:17:13)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.661 s

【讨论】:

    猜你喜欢
    • 2016-09-02
    • 2013-01-03
    • 2020-04-07
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    • 2021-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多