如何在等待异步响应后生成Mocha的it()测试用例
问题原因
Mocha运行测试分为两个固定阶段:
- 收集阶段:同步执行所有
describe块的回调函数,收集所有注册的it()测试用例、钩子配置 - 执行阶段:按照定义顺序执行before系列钩子、测试用例、after系列钩子
你给describe传入了async回调,await后的逻辑会被推入微任务队列延迟执行,等Mocha同步完成全量用例收集时,循环里的it()根本还没完成注册,自然会被全部忽略。
之前尝试用before()钩子解决不生效也是同一个逻辑:before()是执行阶段才会触发的逻辑,此时Mocha早就结束了用例收集流程,在钩子内部注册的it()不会被框架识别。
Mocha从设计上就不支持给
describe回调加async,所有用例注册逻辑必须在describe回调内同步完成。
可行解决方案
根据你的测试数据依赖场景,二选一即可:
方案1:测试文件顶层预拉取数据(优先推荐)
如果测试数据拉取不依赖测试运行时的上下文(比如不需要等测试服务启动、不需要读取测试运行时生成的配置),直接在文件顶层异步拉取数据,拿到数据后再同步执行describe块注册用例,适配所有Mocha版本,逻辑最稳定:
// 顶层await拉取测试数据,不要放在describe内部await const testParams = await <your asynchronous data fetch call> describe('Generated tests', () => { // 这里的逻辑同步执行,Mocha可以正常收集所有用例 testParams.forEach(testParam => { it(`Generated test for ${testParam}`, () => myTestFunc(testParam)) }) })
方案2:开启延迟运行模式
如果测试数据拉取必须依赖测试上下文(比如需要先在钩子中初始化测试服务、连接测试库才能拿到数据),启动Mocha时加上--delay参数开启延迟收集模式,等所有异步准备完成、用例全部注册后手动调用run()触发测试流程:
describe('Generated tests', () => { let testParams; // 依赖测试上下文的异步逻辑放在before里拉取 before(async () => { testParams = await <asynchronous call that relies on test context> }) // 同步注册用例,等执行时直接用拉取到的参数即可 testParams?.forEach(testParam => { it(`Generated test for ${testParam}`, () => myTestFunc(testParam)) }) }) // 所有异步准备完成后调用run()启动测试 ;(async () => { // 此处可放全局异步初始化逻辑 await globalAsyncInit() run() })()
注意:开启延迟模式后必须手动调用全局
run()方法,否则Mocha会一直挂起不会执行测试。
常见踩坑
- 永远不要在
before/after/beforeEach/afterEach这类执行阶段的钩子内部定义it()用例,此时注册的用例不会被Mocha收集 - 循环生成用例时用
const/let声明循环变量,不要用var,避免闭包问题导致所有用例拿到最后一个循环的参数值 - 不要在describe回调内写await逻辑,会直接打断Mocha的用例收集流程
内容的提问来源于stack exchange,提问作者Ya.
相关产品推荐
相关产品推荐

