Общая идея модульных тестов не в том, чтобы использовать реальные вещи, как они:
- Медленно (например, база данных)
- Опасно часто соваться (например, Google Search API)
- Недоступно (например, веб-служба или оборудование)
Для таких сценариев вы предполагаете использовать макеты / заглушки. Другими словами, вещи, которые ведут себя одинаково, но на самом деле под вашим полным контролем.
В вашем случае SpeechRecognitionEngine
, даже если он может быть доступен, будет слишком громоздким для юнит-тестов. Кто / что будет с ним говорить? И даже если вы инициируете событие, зачем создавать экземпляр реального SpeechRecognitionEngine
?
Глядя на MSDN для определения SpeechRecognitionEngine
указывает, что он не реализует интерфейс, что означает, что было бы трудно издеваться / заглушки.
Для этого случая вам нужно обернуть, другими словами, инкапсулировать SpeechRecognitionEngine
в ваш собственный класс, который реализует ваш интерфейс. Затем все, что вам нужно сделать, - это иметь две реализации вашего интерфейса, одну с реальным SpeechRecognitionEngine
для реального распознавания речи, и другой класс для модульных тестов, которые просто имитируют ваш собственный обратный вызов, вместо использования события SpeechRecognized
.
Вы просто меняете один экземпляр на другой, и ваш код не увидит разницы, поскольку они реализуют единый интерфейс.
Если вы просто хотите смоделировать событие , вы просто вызываете обработчик события, так как это метод. Или другой метод, если вы не можете создать EventArgs
. Но проблема в том, что вам придется выставлять внутренние методы извне вашего класса (например, пометить его public
или internal
), и это выглядит неприятно.
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" });