使用Jest、Mongoose和MongoMemoryServer测试时触发栈溢出错误
Jest测试Express应用时MongoDB栈溢出错误解决
错误信息
FAIL src/routes/__test__/signUp.test.ts ● Test suite failed to run RangeError: Maximum call stack size exceeded at Object.get [as ObjectId] (node_modules/mongodb/src/bson.ts:39:3) at Object.get [as ObjectId] (node_modules/mongodb/src/bson.ts:39:3) at Object.get [as ObjectId] (node_modules/mongodb/src/bson.ts:39:3)
测试代码
import request from 'supertest'; import { app } from 'app'; it('Returns a 201 on successful signup', async () => { return request(app) .post('/api/users/signup') .send({ email: 'test@test.com', password: 'password', }) .expect(201); });
测试配置代码
import mongoose from 'mongoose'; import { MongoMemoryServer } from 'mongodb-memory-server'; let mongo: MongoMemoryServer; beforeAll(async () => { process.env.JWT_KEY = 'whateverfornow'; mongo = await MongoMemoryServer.create(); const mongoUri = mongo.getUri(); await mongoose.connect(mongoUri, {}); }); beforeEach(async () => { const collections = await mongoose.connection.db.collections(); for (let collection of collections) { await collection.deleteMany({}); } }); afterAll(async () => { if (mongo) { await mongo.stop(); } await mongoose.connection.close(); });
问题分析与解决方案
这个栈溢出错误是由于ObjectId的getter方法无限递归导致的,通常和依赖版本不兼容、测试配置中的集合操作触发循环引用有关,可按以下步骤解决:
1. 对齐依赖版本
检查package.json中的依赖版本,确保:
mongoose与mongodb版本兼容(mongoose的peer依赖会指定mongodb的兼容范围)mongodb-memory-server版本支持当前使用的mongodb版本
比如,若使用mongoose 7.x,需确保mongodb版本在4.7.x以上,mongodb-memory-server至少为8.x版本。
2. 修改集合清理逻辑
原配置中直接调用mongoose.connection.db.collections()可能在某些版本组合下触发bson相关的循环引用,改用以下两种方式之一:
方式一:通过listCollections获取集合并删除
beforeEach(async () => { const collections = await mongoose.connection.db.listCollections().toArray(); for (const collection of collections) { await mongoose.connection.db.dropCollection(collection.name); } });
方式二:通过mongoose模型清理数据
beforeEach(async () => { await Promise.all(Object.values(mongoose.models).map(model => model.deleteMany({}))); });
3. 手动绑定ObjectId(可选)
若版本调整后仍有问题,可手动指定ObjectId避免循环引用:
import mongoose from 'mongoose'; import { MongoMemoryServer } from 'mongodb-memory-server'; import { ObjectId } from 'mongodb'; // 手动绑定ObjectId mongoose.Types.ObjectId = ObjectId; let mongo: MongoMemoryServer; // 后续配置代码不变...
内容的提问来源于stack exchange,提问作者Vladyslav Makarenko
相关产品推荐
相关产品推荐

