JavaScript中无法直接Mock原生SpeechRecognition,但可通过替换全局构造函数和模拟事件行为实现可控测试假对象,需检查环境、构建可配置Mock类、在测试中验证交互并清理全局状态。

JavaScript 中无法直接 Mock 原生 SpeechRecognition(因它依赖底层系统/浏览器语音服务,且多数浏览器已弃用或限制该 API),但可以通过替换全局构造函数和实例方法来模拟行为,实现测试友好、可控的语音识别假对象。
1. 检查并覆盖全局 SpeechRecognition
现代浏览器(Chrome 仅旧版本支持,Edge/Firefox 不支持,Safari 完全不支持)已逐步移除该 API。测试前先确认环境是否可用,再安全地 mock:
- 用
if (typeof SpeechRecognition === 'undefined')判断是否需要注入 mock - 在测试入口(如 Jest 的
setupFilesAfterEnv或 Mocha 的beforeEach)中定义伪造类 - 将伪造类挂载到
window.SpeechRecognition和window.webkitSpeechRecognition(兼容旧 Chrome)
2. 构建可控制的 Mock 类
模拟关键属性和事件触发逻辑,支持手动触发 result、end、error 等事件:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 构造函数:接受配置项(如是否自动结束、默认识别结果)
-
实例方法:
start()(触发start事件)、stop()(触发end)、abort() -
模拟识别结果:提供
simulateResult(text, confidence = 0.9)方法,生成带SpeechRecognitionEvent结构的 fake event -
事件绑定:用
addEventListener/removeEventListener兼容原生写法(内部用 Map 存储监听器)
3. 在测试中使用 Mock 实例
以 Jest 为例,在测试中主动创建 mock 实例,并验证交互逻辑:
立即学习“Java免费学习笔记(深入)”;
- 调用
recognition.start()后,检查是否触发了start回调 - 调用
recognition.simulateResult('hello'),断言onresult被调用,且event.results[0][0].transcript为'hello' - 触发
simulateError('no-speech'),验证onerror是否收到对应错误码 - 避免真实麦克风权限请求 —— mock 后所有操作纯内存执行
4. 注意兼容性与替代方案
由于原生 API 已不可靠,生产中建议:
- 用
try/catch包裹new SpeechRecognition(),降级为文本输入或按钮选择 - 考虑 Web Speech API 的替代:如调用后端 ASR 服务(Whisper API、Azure Speech)+ 前端音频采集(
MediaRecorder) - 单元测试中优先 mock,E2E 测试可跳过语音识别环节,或用 Cypress 插件模拟事件

















