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
相关产品推荐
相关产品推荐

