首页 > 解决方案 > 在单元测试中等待异步命令

问题描述

我使用基于 https://msdn.microsoft.com/en-us/magazine/dn630647.aspx的异步命令

该命令的执行程序如下所示:

(package) =>
{
    return Task.Run(() =>
    {
        dataProvider.Save(package);
        // emulate long running operation
        for (int i = 0; i < 5000000; ++i)
        {
            string[] ar = new string[1000];
        }
}).ContinueWith(t =>
{
    messagingService.Send(new PackageSavedMessage
    {
        Id = package.Id,
        Name = package.Name,
    });
}, TaskScheduler.FromCurrentSynchronizationContext());

当我单击应用程序中的保存按钮时,它运行良好,即它异步等待,然后ContinueWith触发。

但是当我尝试从单元测试中调用它时

[Test]
public async Task SaveCommand_Test()
{
    using (var scope = _container.BeginLifetimeScope())
    {
        var vm = scope.Resolve<MainViewModel>();
        AsyncCommandBase acb = vm.PackageViewModels[0].SaveCommand as AsyncCommandBase;
        SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
        await acb.ExecuteAsync(package);
    }
}

ContinueWith立即触发,不等待任务完成

如果我没有设置 SynchronizationContext,我会得到一个错误

当前的 SynchronizationContext 不能用作 TaskScheduler。

标签: c#task

解决方案


您的执行人不需要使用ContinueWith; 更现代await的也可以(请注意,await它将自动捕获并恢复其 context,因此不需要显式TaskScheduler):

async (package) =>
{
  await Task.Run(() =>
  {
    dataProvider.Save(package);
    // emulate long running operation
    for (int i = 0; i < 5000000; ++i)
    {
      string[] ar = new string[1000];
    }
  });
  messagingService.Send(new PackageSavedMessage
  {
    Id = package.Id,
    Name = package.Name,
  });
}

推荐阅读