Обертка вокруг ЗАДАЧ в C#

Я использую задачи в WinForms (.NET 4.0) выполнять длительные операции, такие как WCF вызов. Приложение уже в продукте с интенсивным использованием задач (почти все методы, которые используют задачи void).

Во время модульного тестирования мы использовали AutoResetEvents (в реальном коде), чтобы узнать, когда данная задача завершена, затем выполнить утверждение.

Это наводит меня на мысль, что почти все AutoResetEvent пустая трата усилий. Они просто удовлетворяют требованиям модульного тестирования, ничего больше.

Можем ли мы создать оболочку для задач, аналогично, когда выполняется настоящий код... они должны работать в фоновом режиме, а в случае модульного тестирования они должны быть синхронными.

Аналогично ссылке ниже для BackgroundWorker,

http://si-w.co.uk/blog/2009/09/11/unit-testing-code-that-uses-a-backgroundworker/

1 ответ

Решение

Почему вы не можете просто использовать продолжение для задач в вашей оболочке, например так:

var task = ...
task.ContinueWith(t => check task results here)

Также юнит-тесты можно пометить как async, если они имеют тип возврата Task так что вы можете использовать await там, и после этого ваши утверждения:

[Test]
public async Task SynchronizeTestWithRecurringOperationViaAwait()
{
    var sut = new SystemUnderTest();
    // Execute code to set up timer with 1 sec delay and interval.
    var firstNotification = sut.StartRecurring();
    // Wait that operation has finished two times.
    var secondNotification = await firstNotification.GetNext();
    await secondNotification.GetNext();
    // Assert outcome.
    Assert.AreEqual("Init Poll Poll", sut.Message);
}

Другой подход (из той же статьи) заключается в использовании пользовательского планировщика задач, который будет синхронным в случае модульного тестирования:

[Test]
public void TestCodeSynchronously()
{
    var dts = new DeterministicTaskScheduler();
    var sut = new SystemUnderTest(dts);
    // Execute code to schedule first operation and return immediately.
    sut.StartAsynchronousOperation();
    // Execute all operations on the current thread.
    dts.RunTasksUntilIdle();
    // Assert outcome of the two operations.
    Assert.AreEqual("Init Work1 Work2", sut.Message);
}

Же MSDN журнал содержит хорошую статью о лучших практиках для async модульное тестирование. Также async void следует использовать только как обработчик событий, все остальные методы должны иметь async Task подпись.

Другие вопросы по тегам