Каков наилучший способ для unit test асинхронного метода?
Я не могу найти ответ .NET на эту проблему, о которой я бы подумал, был бы довольно распространен.
Каков наилучший образец для модульного тестирования асинхронного метода?
Очевидно, мне нужно вызвать метод, а затем посмотреть, срабатывает ли обратный вызов, но есть ли лучший способ, чем просто спящий бит, а затем проверка флага, установленного обратным вызовом? Управление флагами становится немного грязным, когда выполняется несколько тестов.
Ответы
Ответ 1
Обычно я использую анонимный делегат и waithandle. Например, у меня есть функция в моем презентаторе, называемая SetRemoteTableName. Когда имя установлено, оно также вызывает событие. Я хочу проверить это событие, которое возникает асинхронно. Тест выглядит следующим образом:
[TestMethod]
[WorkItem(244)]
[Description("Ensures calling SetRemoteTableName with a valid name works
AND raises the RemoteTableNameChange event")]
public void SetRemoteTableNamePositive()
{
string expected = "TestRemoteTableName";
string actual = string.Empty;
AutoResetEvent are = new AutoResetEvent(false);
SQLCECollectorPresenter presenter = new SQLCECollectorPresenter();
presenter.RemoteTableNameChange += new EventHandler<GenericEventArg<string>>(
delegate(object o, GenericEventArg<string> a)
{
actual = a.Value;
are.Set();
});
presenter.SetRemoteTableName(expected);
Assert.IsTrue(are.WaitOne(1000, false), "Event never fired");
Assert.AreEqual(actual, expected);
}
Ответ 2
Разделите код так, чтобы логика находилась в синхронном бите кода, который вызывается тонкой асинхронной оболочкой.
Тогда большинство ваших модульных тестов могут протестировать синхронный код.
Ответ 3
Есть ли лучший способ, чем просто спать немного, а затем проверить флаг, установленный обратным вызовом?
Замените флаг дескриптором ожидания. Вместо установки флага установите дескриптор ожидания. Вместо того, чтобы спать, а затем проверять, установлен ли флаг, ждать команды wait... и ждать с таймаутом, так что если вы просыпаетесь из-за истечения таймера вместо пробуждения, потому что ручка, на которой вы ждали, была уволена по обратному вызову, то вы знаете, что тест не прошел (т.е. обратный вызов не был вызван в течение периода ожидания).