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

Mocha中async/await测试超时失败,Docker容器测试挂起求助

Docker Mocha测试超时问题排查

问题描述

我用Mocha编写测试用例,借助dockerode库执行Docker容器的停止、启动及健康检查操作,采用async/await语法,但运行时持续报错:

Error: Timeout of 120000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

控制台已输出container healthy,但测试始终挂起,直到超时触发上述错误。测试代码如下:

describe('docker container test', () => {
    let docker

    before(() => {
        docker = new Docker()
    })

    after( () => {
        docker = null
    })

it('simple docker test', async () => {
        try {
            container = await getDockerContainerByName(docker, containerName)
            await stopDocker(docker, container)
            await startDocker(docker, container)
            await waitForContainerToBeHealthy(docker, container)
            console.log("container healthy")
        } catch(error) {
            console.log("Error occurred "+ JSON.stringify(error))
        }
    }).timeout(120000)
})

async waitForContainerToBeHealthy (docker, container) {
        await invokeUntil(async (retry, complete) => {
            return dockerTestHelper.inspectDockerContainer(docker, container).then( (data) => {
                if(// check if container is healthy) {
                    complete()
                } else {
                    retry()
                }
            })
        })
    }

问题原因

核心问题出在waitForContainerToBeHealthy函数中的invokeUntil调用:

  • 你使用await等待该函数完成,但invokeUntil内部的complete()并未正确触发Promise的resolve,导致这个函数始终处于pending状态,整个测试用例无法正常结束,最终触发超时。
  • 此外,测试用例中的container变量未声明,会成为全局变量,虽不是超时直接原因,但属于潜在代码问题。

解决方案

1. 重构健康检查逻辑(替换invokeUntil)

放弃依赖invokeUntil的回调式重试,改用基于Promise的循环重试逻辑,确保状态变化时能正确resolve:

async waitForContainerToBeHealthy(docker, container, timeout = 120000, interval = 2000) {
    const startTime = Date.now();
    while (Date.now() - startTime < timeout) {
        const data = await dockerTestHelper.inspectDockerContainer(docker, container);
        // 替换为实际的健康检查条件,比如容器状态的健康字段
        if (data.State.Health?.Status === 'healthy') {
            return;
        }
        // 间隔指定时间后重试
        await new Promise(resolve => setTimeout(resolve, interval));
    }
    throw new Error('容器健康检查超时');
}

2. 修复变量声明问题

在测试用例的it块中声明container变量,避免全局污染:

it('simple docker test', async () => {
    let container = await getDockerContainerByName(docker, containerName);
    await stopDocker(docker, container);
    await startDocker(docker, container);
    await waitForContainerToBeHealthy(docker, container);
    console.log("container healthy");
}).timeout(120000);

3. 移除冗余的try/catch(可选)

如果需要测试在出错时直接失败,不要用try/catch吞掉错误,Mocha会自动捕获Promise的reject,便于定位问题。

内容的提问来源于stack exchange,提问作者chan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 07:10:17