JEST+Supertest测试Express接口报环境已销毁等错误求助
问题修复方案
报错根因分析
- 报错
TypeError: Right-hand side of 'instanceof' is not callable根因:- 测试文件未导入mongoose依赖,直接调用
mongoose.connect访问未定义变量,触发类型校验异常 - server.js加载时直接执行
connectDB(),测试环境下数据库连接依赖加载时序异常也会触发该错误
- 测试文件未导入mongoose依赖,直接调用
- 报错You are trying to import a file after the Jest environment has been torn down根因:
- 测试文件的
beforeEach仅定义了异步connectDB函数,没有实际执行,异步操作在测试用例跑完后才触发,此时Jest环境已销毁 - server.js中
readdirSync动态加载路由的时序和测试异步执行冲突,路由导入、数据库连接等操作在测试结束后才完成
- 测试文件的
修复步骤
1. 修改server.js,避免加载时自动连接数据库
仅在非测试环境自动连接数据库,测试环境的数据库连接由测试脚本控制:
// 替换原有的connectDB(); if (process.env.NODE_ENV !== 'test') { connectDB(); }
2. 修复测试文件代码
补全依赖导入,正确控制异步连接的生命周期:
const app = require("../server"); const supertest = require("supertest"); const mongoose = require("mongoose"); const request = supertest(app); // 所有测试开始前连接数据库 beforeAll(async () => { try { await mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false, useCreateIndex: true, }); } catch (error) { console.log("Mongoose Error", error); process.exit(1); } }); // 所有测试结束后关闭数据库连接,释放资源 afterAll(async () => { await mongoose.connection.close(); }); it("Testing to see if Jest works", () => { expect(1).toBe(1); }); // 接口测试示例参考 it("GET /api/xxx 接口返回符合预期", async () => { const res = await request.get("/api/xxx"); expect(res.statusCode).toBe(200); });
3. 修改package.json的test命令,指定测试环境
"scripts": { "test": "NODE_ENV=test jest --runInBand --detectOpenHandles" },
Windows环境如果无法识别NODE_ENV变量,可先安装
cross-env包,将命令改为cross-env NODE_ENV=test jest --runInBand --detectOpenHandles即可
优化建议
- 测试环境使用独立的MongoDB测试库,不要和开发/生产库共用,避免测试数据污染业务数据
- 每个单测结束后清空对应集合的数据,保证所有测试用例的上下文独立性
- 不需要连接数据库的纯逻辑测试可以mock掉mongoose依赖,大幅提升测试执行速度
- server.js中引入的
erroHandler存在拼写错误,建议修正为正确的errorHandler,避免中间件加载异常
内容的提问来源于stack exchange,提问作者Imran Abdalla
相关产品推荐
相关产品推荐

