使用ShellJS启动go程序阻塞codeceptjs测试,如何不中断后续JS执行?
问题根因
你遇到的阻塞问题本质是shelljs的exec方法默认同步执行,调用后会等待子进程完全终止才会返回结果,只要你启动的Go应用不退出,后续的测试代码就会被永久阻塞,无法向下执行。你原代码里传入的第二个参数true对应的是silent配置,不会改变同步执行的逻辑,所以还是会出现阻塞。
解决方案
方案1:使用shell.exec的异步模式
给exec方法传入async: true配置项,开启异步执行模式,调用后会立刻返回进程实例,不会阻塞后续代码:
const shell = require('shelljs') let goAppProcess // 存储进程实例,用于后续清理 Given('Member starts call', async () => { // 开启异步执行,不会等进程退出就返回 goAppProcess = shell.exec('./myGoApplication -cc call', { async: true, silent: false // 不需要打印Go应用日志可以改成true }) // 可选:加短等待兜底,确保Go应用基础初始化完成 await new Promise(resolve => setTimeout(resolve, 1000)) }); // 测试结束后清理进程,避免残留 After(() => { if (goAppProcess) { goAppProcess.kill() } })
方案2:使用Node.js原生child_process.spawn(更推荐)
Node.js内置的child_process.spawn方法默认就是异步的,对长期运行的后台服务控制更灵活,也支持自定义启动完成判断逻辑,比shelljs更适合这类场景:
const { spawn } = require('child_process') let goAppProcess Given('Member starts call', async () => { goAppProcess = spawn('./myGoApplication', ['-cc', 'call']) // 监听输出判断启动状态,比硬等待更可靠 await new Promise((resolve, reject) => { goAppProcess.stdout.on('data', (data) => { console.log(`Go应用输出: ${data}`) // 示例:匹配Go应用启动成功的日志,匹配到就进入下一步 if (data.toString().includes('server started')) { resolve() } }) goAppProcess.stderr.on('data', (data) => { console.error(`Go应用错误: ${data}`) }) goAppProcess.on('error', (err) => { reject(err) }) // 超时兜底,避免启动失败一直卡顿 setTimeout(() => reject(new Error('Go应用启动超时')), 5000) }) }); After(() => { if (goAppProcess) { goAppProcess.kill('SIGINT') } })
注意事项
- 测试结束后必须手动杀掉启动的Go进程,否则会残留孤儿进程,占用端口等资源,影响后续测试运行
- 不要启动应用后立刻执行后续测试步骤,建议通过匹配启动日志、调用探活接口等方式确认应用初始化完成,避免后续用例提前执行失败
- 如果不需要在控制台查看Go应用的运行日志,可以配置日志输出到本地文件,避免测试输出被刷屏
内容的提问来源于stack exchange,提问作者Kyryl Zotov
相关产品推荐
相关产品推荐

