单元测试和多个异步任务

4
我正在创建单元测试,以帮助构建一些代码,该代码将接受来自我的控制器的入站请求并排队(如果需要)。
在我的单元测试中,我希望两行代码几乎同时触发,尽管这两次调用之间有2秒的延迟。这允许触发逻辑的第一个分支,然后在第二个调用中,由于已经看到了传递的数据,使用备用逻辑分支。
我已经接近目标,但感觉有些混乱。我正在使用以下内容,它会立即传递我的第一个调用,并继续执行随后的代码行。
Task.Factory.StartNew(() => stubbedQueueHandler.QueueProcessor(setupModel));

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

await Task.Delay(10000);

然而,单元测试在第一次调用完成之前就已经结束,这导致进程被终止。唯一允许第一次调用完成的方法是添加一个await Task.Delay()语句即可解决问题。
我明白为什么会这样,因为我实际上已经交出了调用,没有期望有响应返回。我不想开始使用任务延迟,我相信这只是我对异步编程理解不够深刻的问题 :o)。
2个回答

4
您需要捕获启动QueueProcessorTask,并在第二次调用存根后等待它:
public async Task FooTestAsync()
{
    var task = Task.Run(() => stubbedQueueHandler.QueueProcessor(setupModel));
    await Task.Delay(2000);

    stubbedQueueHandler.QueueProcessor(setupModel);
    await task;
}

这样做可以确保操作在完成之前被执行,因为QueueProcessor会同步阻塞直到其操作完成。

4

您需要避免在异步代码中使用Thread.Sleep()。

请参考图5“异步方式”做事情

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

you should avoid mixing async and blocking code. Mixed async and blocking code can cause deadlocks, more-complex error handling and unexpected blocking of context threads.


1
好的,这是我开始养成的一个坏习惯,我会在以后尽快纠正它!:o) - Sulphy
这更像是对楼主问题的评论,而不是答案。 - Yuval Itzchakov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接