单元测试和多个异步任务

时间:2015-11-10 16:06:20

标签: c# asp.net asynchronous asp.net-web-api async-await

我正在创建单元测试,以帮助构建一些代码,这些代码将接受并排队(如果需要)来自我的控制器的入站请求。

在我的单元测试中,我希望同时启动两行代码,尽管调用之间有2秒的延迟。这允许我的逻辑的第一个分支被触发,然后在第二次调用时,因为已经看到传递的数据使用逻辑的备用分支。

我已经走近了,但感觉很乱。我正在使用以下内容,它会立即关闭我的第一个电话并转到后续的代码行。

Task.Factory.StartNew(() => stubbedQueueHandler.QueueProcessor(setupModel));

Thread.Sleep(2000);
//second call
stubbedQueueHandler.QueueProcessor(setupModel);

await Task.Delay(10000);

然而,单元测试在第一次调用结束之前结束,这反过来又杀死了整个过程。允许第一个调用完成的唯一方法是放置一个await Task.Delay()行来完成这个操作。

我可以理解为什么会这样做,因为我已经有效地切换了电话而没有期待回复。我不想开始使用任务延迟,我确信这只是我缺乏理解,这就是异步编程时的问题:o)。

2 个答案:

答案 0 :(得分:4)

你需要的是捕获启动Task的{​​{1}}并在第二次调用存根之后等待它:

QueueProcessor

这样,您可以确保在操作完成之前完成操作,前提是public async Task FooTestAsync() { var task = Task.Run(() => stubbedQueueHandler.QueueProcessor(setupModel)); await Task.Delay(2000); stubbedQueueHandler.QueueProcessor(setupModel); await task; } 将同步阻塞,直到操作完成。

答案 1 :(得分:3)

您需要避免将Thread.Sleep()与异步代码一起使用。

请参阅Figure 5 The “Async Way” of Doing Things

To Do This                                Instead of This            Use This
Retrieve the result of a background task  Task.Wait or Task.Result   await
Wait for any task to complete             Task.WaitAny               await Task.WhenAny
Retrieve the results of multiple tasks    Task.WaitAll               await Task.WhenAll
Wait a period of time                     Thread.Sleep               await Task.Delay
     

你应该避免混合异步和阻塞代码。混合的异步和阻塞代码可能导致死锁,更复杂的错误处理和意外阻塞上下文线程。