测试驱动的异步任务

时间:2010-12-07 19:25:59

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

我正在寻找关于该主题的一般想法和/或链接,尽管我目前的具体动机是与使用BackgroundWorker和/或TPL的进度报告相关的UI任务。我对异步编程的经验水平一般是新手。我最了解的测试工具是NUnit和Rhino。

一些头脑风暴突破了我的头脑:

  1. 不要打扰 - 它太复杂了,你最终会测试BGW或TPL。
  2. 制作某种假货或假货。
  3. 使用EventWaitHandles

1 个答案:

答案 0 :(得分:6)

单元测试异步代码并不是世界上最简单的事情,正如我在为Nito.Async库编写单元测试时所学到的。 :)

首先,您要定义实际要测试的内容。您是否只想测试是否执行了异步操作,还是要确保您的BGW /任务正确地同步其UI进度报告?

测试操作非常简单:只需等待操作完成,然后检查后置条件。 (但是,请注意BGW RunWorkerCompleted将在ThreadPool线程上引发,除非您给它一个同步上下文,如下例所示。)

测试正确的同步(例如,每段代码在正确的线程上运行)更复杂。

对于每个测试,您需要建立同步上下文。这将模拟UI同步上下文。我的Nito.Async库可能对此有所帮助;它有一个ActionThread,它是一个单独的线程,包含适合拥有EAP组件(例如BGW)和调度任务(例如TaskScheduler.FromCurrentSynchronizationContext)的同步上下文。

可以像这样使用(使用MSTest示例):

[TestMethod]
public void Test()
{
  using (ActionThread thread = new ActionThread())
  {
    thread.Start();

    // Anything passed to Do is executed in that ActionThread.
    thread.Do(() =>
    {
      // Create BGW or call TaskScheduler.FromCurrentSynchronizationContext.
    });

    // The thread is gracefully exited at the end of the using block.
  }
}

我发现Thread.CurrentThread.ManagedThreadIdThread.CurrentThread.IsThreadPoolThread是检查正确同步的最简单方法。如果您的测试代码是在ActionThread.Do内运行的,那么它应该将其进度更新(和完成通知)与ActionThread同步。

很多Nito.Async单元测试都以这种方式使用ActionThread,因此您可以查看各种示例。