You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 11:42:28