node.js - 如何在 Jest afterAll 钩子(Hook)中关闭 Express 服务器

标签 node.js express jestjs axios integration-testing

我正在尝试使用 Jest 为我的 Express 服务器编写集成测试。由于 Jest 并行运行测试(并且我想避免使用 --runInBand 依次运行测试),我正在使用 get-port用于查找随机可用端口的库,以便不同的测试套件不会发生端口冲突。

我的测试都成功运行,唯一的问题是服务器无法在 afterAll Hook 内正常关闭。这会导致 Jest 在控制台中打印以下内容...

Jest did not exit one second after the test run has completed.
This usually means that there are asynchronous operations that weren't stopped in your tests.
Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.

当我使用 --detectOpenHandles 标志时,Jest 只是在测试完成后挂起。控制台不会打印任何内容。

这是我的测试代码...

let axios = require('axios')
const getPort = require('get-port')
const { app } = require('../../index')
const { Todo } = require('../../models')

// set reference to server to access
// from within afterAll hook
let server

beforeAll(async () => {
  const port = await getPort()
  axios = axios.create({ baseURL: `http://localhost:${port}` })
  server = app.listen(port)
})

afterAll(() => {
  server.close()
})

describe('GET /todos', () => {
  it('returns a list of todos', async () => {
    const { data: todos } = await axios.get('/todos')
    todos.forEach(todo => {
      expect(Todo.validate(todo)).toEqual(true)
    })
  })
})

最佳答案

我在这个问题的 github 线程上。这正是适合我的配置。在 package.json 中

"test": "jest --no-cache  --detectOpenHandles --runInBand --forceExit",

这是测试文件中的配置

afterEach(async () => {
  await server.close();
});

afterAll(async () => {
  await new Promise(resolve => setTimeout(() => resolve(), 10000)); // avoid jest open handle error
});

beforeEach(() => {
  // eslint-disable-next-line global-require
  server = require('../index');
  jest.setTimeout(30000);
});

或者您只有 afterAll 为测试主体中的每个测试单独设置超时和 settimeout。这是下面的示例

afterEach(async () => {
  await server.close();
});

afterAll(async () => {
  await new Promise(resolve => setTimeout(() => resolve(), 10000)); // avoid jest open handle error
});

beforeEach(() => {
  // eslint-disable-next-line global-require
  server = require('../index');
});


describe('POST /customers', () => {
  jest.setTimeout(30000);
  test('It creates a customer', async () => {
    const r = Math.random()
      .toString(36)
      .substring(7);
    const response = await request(server)
      .post('/customers')
      .query({
        name: r,
        email: `${r}@${r}.com`,
        password: 'beautiful',
      });
    // console.log(response.body);
    expect(response.body).toHaveProperty('customer');
    expect(response.body).toHaveProperty('accessToken');
    expect(response.statusCode).toBe(200);
  });
});

关于node.js - 如何在 Jest afterAll 钩子(Hook)中关闭 Express 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59011575/

相关文章:

javascript - 在 enzyme 浅渲染中将 jest.fn() 函数传递给 mapDispatchToProps

javascript - 使用 ipfs (js-ipfs-http-client) 将完整目录上传到 IPFS

node.js - 如何像 Google 文档一样在羽毛笔编辑器中执行跟踪更改?

javascript - 如何在开发中运行多个 Node.js 应用程序

javascript - 带 Express 的 Aurelia 的最小示例

javascript - 使用 redux 操作创建器调用 onClick() 时应该测试什么?

typescript - Vue/Typescript/Jest - Jest 单元测试语法错误 : Unexpected token import

javascript - 使用 elemMatch 从数组 Node.js 返回一个对象

javascript - 单元测试中的代码覆盖率

node.js - 如何使用node.js从mongodb获取数据并显示