node.js - 如何在 Jest afterAll 挂钩中关闭 Express 服务器
问题描述
我正在尝试使用 Jest 为我的 Express 服务器编写集成测试。由于 Jest 并行运行测试(并且我想避免使用 顺序运行测试--runInBand
),因此我使用get-port库来查找随机可用端口,以便不同的测试套件不会发生端口冲突。
afterAll
我的测试全部成功运行,唯一的问题是服务器未能在钩子内正确关闭。这会导致 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 为测试主体中的每个测试单独设置超时和设置超时。下面的示例
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);
});
});
推荐阅读
- php - 有什么方法可以避免在 Laravel 5.7 Eloquent 中加载父级时加载这些 $with 模型?
- php - 实施具有强客户身份验证的条带
- jquery - jQuery验证后将表单发布数据传递给控制器功能
- javascript - NGRX dispatch 和 select 的执行顺序
- android - Android Studio 3.5:无法解析 LocalBroadcastManager
- html - 如何使用 flexbox 突出显示导航栏链接的整个“框部分”?
- android - 发布到 google play 的应用程序中是否允许使用这种类型的课程?
- java - 创建 Java Swing 弹出窗口以请求详细信息
- javascript - 如何在 React 项目中加载 Google Places JS API 库?
- angular - 在 Openlayers 5 中渲染字体图标时出错