手动触发 SpeechRecognizedEvent

Manually fire SpeechRecognizedEvent

我需要手动触发 SpeechRecognizedEvent 进行单元测试,所以我无法使用 SpeechRecognitionEngine 中的 EmulateSpeech 方法

编辑:

我已经将 SpeechRecognition 封装到一个单独的 Class 中,它有自己的接口来模拟它。

我需要调用该事件,因为我有一个 AutoResetEvent,我在事件期间对其进行了 Set()。单元测试需要这个才能继续。

单元测试的总体思路是不要使用真实的东西,因为它们要么:

  1. 慢(例如数据库)
  2. 经常戳很危险(例如Google搜索API)
  3. 不可用(例如网络服务或硬件)

对于这种情况,您应该使用 mocks/stubs。换句话说,行为相同的事物,但实际上在您的完全控制之下。

在你的情况下 SpeechRecognitionEngine,即使它可能可用,对于单元测试来说也太麻烦了。 Who/what会说话吗?而且就算触发了事件,为什么要实例化一个真实的实例SpeechRecognitionEngine?

查看 MSDN 的 SpeechRecognitionEngine 定义表明它没有实现接口,这意味着很难 mock/stub。

对于这种情况,您需要包装,换句话说,将 SpeechRecognitionEngine 封装到您自己的 class 中,它实现了您的接口。然后,您需要做的就是拥有您的接口的两个实现,一个具有真正的 SpeechRecognitionEngine 用于真实的语音识别,另一个具有 class 用于单元测试,它只是模仿您自己的回调,而不是使用 SpeechRecognized 事件。

您只需将一个实例换成另一个实例,您的代码将看不出有什么不同,因为它们实现的是单一接口。

如果你只是想模拟一个事件,你只需要调用一个事件处理器,因为这是一个方法。或者另一种方法,如果你不能创建一些 EventArgs。但问题是您必须从 class 外部公开内部方法(例如将其标记为 publicinternal),这看起来确实令人讨厌。

private void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
    this.ProcessSpeechRecognition(e.Result);
}

public void ProcessSpeechRecognition(RecognitionResult result)
{
    // your logic here
}

然后在测试中你只需调用类似于下面的东西:

ProcessSpeechRecognition(new RecognitionResult { Text = "test" });

尽管之前发布了描述 TDD 最佳实践的答案;这是特定于 SpeechRecognitionEngine.

的答案

微软已经想到了语音识别的仿真。这是 SpeechRecognitionEngine.EmulateRecognize Method:

的 MSDN 文章

https://docs.microsoft.com/en-us/dotnet/api/system.speech.recognition.speechrecognitionengine.emulaterecognize