等待在另一个方法中启动的任务

时间:2013-01-10 21:55:06

标签: c# .net unit-testing async-await

我需要确保任务完成后再进行剩余的单元测试。

但是这是一个在另一个方法中等待的任务(我正在对该方法进行单元测试。)

我已经尝试等待任务或调用task.Wait()但每次测试都不起作用。

实际方法如下:

private async void DoStuff(long idToLookUp)
{
    IOrder order = await orderService.LookUpIdAsync(idToLookUp);   

    OtherStuff = false;
}    

我正试图对它进行单元测试:

[TestMethod]
public void TestDoStuff()
{
    //+ Arrange
    var lookupTask = Task<IOrderableTest>.Factory.StartNew(() => validOrder);
    orderService.LookUpIdAsync(Arg.Any<long>()).Returns(lookupTask);

    //+ Act
    myViewModel.DoStuff();
    await lookupTask;

    //+ Assert
    myViewModel.OtherStuff.Should().BeFalse();
}

失败的方式非常无益。 In It导致另一个测试失败,“测试运行时代理进程已停止”。 (据我所知,这意味着后台线程在测试运行时抛出异常。)

所以我想知道如何让我的代码等待单元测试完成。

我看到this答案似乎相当不错。但它更倾向于调用该方法。我不是在说它,我只是完成任务。

注意:我使用ansyc包定位.NET 4.0。

2 个答案:

答案 0 :(得分:6)

你永远不应该有一个void返回async方法,除非它将成为一个事件处理程序(在这种情况下你别无选择)。当async方法为void时,您无法知道它何时结束。

该方法应该返回Task(如果没有有意义的结果,则返回Task<T>,只是表明它已完成)。

一旦它返回Task,您可以在测试时await,或者使用Wait,如果这是合适的话。

您正在等待该方法所依赖的任务之一,但这并不意味着它已经完成了自己的代码。这意味着您的测试引入了竞争条件。

答案 1 :(得分:0)

一旦命中await关键字,该调用await myViewModel.DoStuff();就会返回(除非它很快完成)。此外,正如Slaks所提到的,你无法等待一个无效的返回方法。

然后你等待var lookupTask = Task<IOrderableTest>.Factory.StartNew(() => validOrder); 除了返回IOrderableTest之外,它似乎没什么用。

另外我不认为你应该做await lookupTask,这将再次返回给调用者,在这种情况下,TestRunner不会/可能不会期望这个。

您应该使用lookupTask.Wait()(这是阻止调用);并确保myViewModel.DoStuff();也需要足够的时间来完成。

摘要

private async Task DoStuff(long idToLookUp)
{
    IOrder order = await orderService.LookUpIdAsync(idToLookUp);   

    OtherStuff = false;
    return;
}

....

 var task = myViewModel.DoStuff();
 Task.WaitAll(task, lookupTask);