在C#中的TASK周围包装

时间:2017-04-20 07:24:44

标签: unit-testing asynchronous c#-4.0 task-parallel-library task

我在WinForms(.NET 4.0)中使用任务来执行WCF调用之类的冗长操作。应用程序已经在大量使用任务的产品中(几乎所有使用任务的方法都是void)。

在单元测试期间,我们使用AutoResetEvent s(在实际代码中)找出给定任务何时完成然后执行断言。

这让我觉得几乎所有AutoResetEvent都是浪费精力。它们只是满足单元测试需求,没有别的。

我们可以在实际代码运行时同样创建一个包装器的包装器......它们应该在后台工作,如果是单元测试,它们应该是同步的。

类似于BackgroundWorker的以下链接。

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

1 个答案:

答案 0 :(得分:1)

为什么不能简单地在包装器中使用continuation来继续执行,如下所示:

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

另外,unit tests can be marked as 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杂志包含不错的article about best practices for async unit testing。此外async void仅应用作事件处理程序,所有其他方法应具有async Task签名。