node.js - 在 express 应用程序中测试默认错误处理程序会导致超时

标签 node.js express jestjs supertest ts-jest

在测试 express 应用程序的默认错误处理程序时,它会导致超时。该函数如下所示:

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."

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

最佳答案

对于 express V4,来自 Error Handling#Catching Errors医生,我们知道:

For errors returned from asynchronous functions invoked by route handlers and middleware, you must pass them to the next() function, where Express will catch and process them.

虽然测试用例中mock的underlyingFunction是同步的,但是在路由中,async/await语法将这个路由handler转为异步代码。

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

例如

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

关于node.js - 在 express 应用程序中测试默认错误处理程序会导致超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68923821/

相关文章:

node.js - 使用 ava 和 proxyquire 用 sinon 加载模块后无法 stub 方法

javascript - 在模拟调用中等待所有 promise

jestjs - 如何在 JEST 中测试 DOM 操作

javascript - 期望对象具有所有给定的属性

node.js - Node.JS 中的垃圾收集套接字

node.js - 使用 Digital Ocean 和 FlightPlan.js 时 Node 应用程序出错 - 所有配置的身份验证方法均失败

node.js - Node 找不到 express 模块?

javascript - 如何正确获取 promise 的返回值?

ios - React Native - 无法构建 DependencyGraph :Cannot read property 'root' of null

javascript - Node.js 远程调试不起作用