Docker部署下Mocha+Chai测试超时问题求助(已调用done())
Docker Compose下Mockgoose连接MongoDB超时问题排查与解决
看起来你遇到的核心问题是Mockgoose在Docker容器环境下无法正常初始化,导致测试的before hook一直卡住超时。本地运行正常但Docker里出问题,通常和容器内的文件系统权限、依赖兼容性或者Mockgoose本身的局限性有关。下面是几个针对性的解决方案:
1. 替换停止维护的Mockgoose为mongodb-memory-server
Mockgoose已经停止更新很长时间了,官方现在推荐使用mongodb-memory-server——它直接在内存中启动一个MongoDB实例,不需要依赖本地文件系统,在Docker环境下兼容性更好,也能避免文件权限类问题。
步骤:
- 安装依赖:
npm install mongodb-memory-server --save-dev - 修改你的MongoDB连接代码:
import mongoose from 'mongoose'; import { MongoMemoryServer } from 'mongodb-memory-server'; let mongoServer: MongoMemoryServer; export const connectMock = async () => { // 创建内存中的MongoDB实例 mongoServer = await MongoMemoryServer.create(); const mongoUri = mongoServer.getUri(); await mongoose.connect(mongoUri, { useNewUrlParser: true, useUnifiedTopology: true }); console.log('Mock MongoDB Connected (in-memory)'); }; // 测试结束后清理资源 export const disconnectMock = async () => { await mongoose.disconnect(); await mongoServer.stop(); }; - 简化测试用例(用async/await替代done回调,减少回调嵌套带来的潜在问题):
describe('Testing the API', () => { before(async () => { await mongodb.connectMock(); }); after(async () => { await mongodb.disconnectMock(); }); it('OK, adding new employee', async () => { const res = await request(app) .put('/add') .send(<some JSON data>); // 你的断言逻辑,比如: expect(res.status).to.equal(200); }); it('OK, getting all employees', async () => { const res = await request(app).get('/all'); expect(res.body).to.be.an('array'); }); // 其他测试用例同理 });
2. 修复Mockgoose在Docker中的文件权限问题
如果你坚持使用Mockgoose,需要解决它的临时文件存储权限问题:Mockgoose需要在容器内创建临时文件,但默认的容器目录可能是只读的,导致初始化卡住。
步骤:
- 在
docker-compose.yml中给测试容器挂载一个可写的卷,并设置环境变量指定临时目录:api_testing_container: build: . volumes: - ./mockgoose-tmp:/tmp/mockgoose environment: - MOCKGOOSE_TMP_DIR=/tmp/mockgoose depends_on: mongo: condition: service_healthy REST_API_app: condition: service_started - 同时确保MongoDB容器的健康检查(保证它真的就绪后测试容器才启动):
mongo: image: mongo:latest healthcheck: test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"] interval: 5s timeout: 5s retries: 5 - 在
connectMock方法中指定临时目录:export let connectMock = () => { return new Promise((resolve, reject) => { let mockgoose: Mockgoose = new Mockgoose(mongoose); // 设置Mockgoose的临时存储目录 mockgoose.setTmpDir(process.env.MOCKGOOSE_TMP_DIR || '/tmp/mockgoose'); mockgoose.prepareStorage() .then(() => { const uri: string = 'mongodb://mongo:27017/rest_api_container'; return mongoose.connect(uri, { useNewUrlParser: true, useUnifiedTopology: true }); }) .then((res) => { console.log('Mock MongoDB Connected'); resolve(res); }) .catch((err: any)=> { console.log(err); reject(err); }); }) }
3. 检查依赖版本兼容性
Mockgoose对Mongoose的版本有严格要求,比如旧版Mockgoose(v8及以下)只支持Mongoose v5.x,如果你用了Mongoose v6+,就会出现初始化卡住的问题。可以运行以下命令检查版本匹配:
npm list mongoose mockgoose
如果版本不匹配,要么降级Mongoose,要么升级到支持对应版本的Mockgoose分支(但注意Mockgoose已经停止维护,升级意义不大)。
内容的提问来源于stack exchange,提问作者Yatin Gaikwad
相关产品推荐
相关产品推荐

