C# 测试驱动异步任务
我正在寻找关于这个主题的一般想法和/或链接,尽管我目前的具体动机是与使用BackgroundWorker和/或TPL的进度报告相关的UI任务。我的异步编程经验一般是新手。我最熟悉的测试工具是NUnit和Rhino 我脑子里突然闪现出一些想法:C# 测试驱动异步任务,c#,unit-testing,asynchronous,task-parallel-library,async-await,C#,Unit Testing,Asynchronous,Task Parallel Library,Async Await,我正在寻找关于这个主题的一般想法和/或链接,尽管我目前的具体动机是与使用BackgroundWorker和/或TPL的进度报告相关的UI任务。我的异步编程经验一般是新手。我最熟悉的测试工具是NUnit和Rhino 我脑子里突然闪现出一些想法: 不用麻烦了,这太复杂了,你只需要测试BGW或TPL就可以了 做一些假货或嘲弄 使用EventWaitHandles 单元测试异步代码并不是世界上最简单的事情,正如我在为我的库编写单元测试时所了解的那样: 首先,您需要定义您实际想要测试的内容。您只是想测试是
单元测试异步代码并不是世界上最简单的事情,正如我在为我的库编写单元测试时所了解的那样: 首先,您需要定义您实际想要测试的内容。您只是想测试是否执行了异步操作,还是想确保BGW/任务正确同步其UI进度报告 测试操作非常简单:只需等待操作完成,然后检查后置条件。(但是,请注意,BGW
RunWorkerCompleted
将在ThreadPool
线程上引发,除非您像下面的示例那样为其提供同步上下文)
测试正确的同步(例如,每段代码都在正确的线程上运行)更加复杂
对于每个测试,您都需要建立一个同步上下文。这将模拟UI同步上下文。我的Nito.Async库可能会对此有所帮助;它有一个ActionThread
,它是一个单独的线程,包含一个适合拥有EAP组件(例如BGW)和调度任务(例如TaskScheduler.FromCurrentSynchronizationContext
)的同步上下文
它可以这样使用(使用MSTest示例):
我发现Thread.CurrentThread.ManagedThreadId
和Thread.CurrentThread.IsThreadPoolThread
是检查正确同步的最简单方法。如果测试代码是从ActionThread.Do
中运行的,那么它应该将其进度更新(和完成通知)同步到该ActionThread
很多Nito.Async单元测试都以这种方式使用
ActionThread
,所以您可以在那里查找各种示例。您能更具体一点吗?也许发布一些代码,这样我们就可以看到你的代码是如何构造的,并相应地回答…@BFree。是的,这个问题很敏感,因此可能太模糊了,但我现在的任何代码都不适合简短的帖子或快速的回答。例如,如果问题是关于开始使用mocks,也许有人会建议Rhino和wiki一起使用,也许还有一篇关于开始使用它的好博文,以及他们自己经验中的一些技巧。干杯!这就是我要说的!我想你写这篇文章是为了让异步的生活变得更简单,没有真正的替代方案。下载中是否包含您的测试?一个人必须对第三方物流有多了解才能理解你的代码?我现在正在看你的博客。例如,在博客上查看ProgressReporter代码,以及如何在不需要制作win表单或其他ui项目的情况下对其进行测试。好东西!!该库最初是为了帮助编写EAP组件而编写的。但是,请注意,VS的未来方向(如VS异步CTP所示)引入了TAP,它将(我希望)取代EAP。因此,Nito.Async的某些部分在几年内将不再适用。不过,它仍然有几个有用的组件,例如ActionThread
。该类有两个用途:允许Console/Windows服务程序具有同步上下文;并使我的单元测试更容易编写。:)单元测试包含在源代码中。异步目前没有使用任何TPL。TPL设计得非常好,不需要像Nito.Async在.NET4.0之前的版本那样的“填补空白”库。EAP=;TAP=基于任务的异步模式。
[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.
}
}