【发布时间】:2014-10-21 08:23:15
【问题描述】:
我尝试为视图模型编写单元测试,但在尝试验证 ICommand 两次调用异步方法时卡住了。
我将 Moq 用于我的依赖项。 我是这样设置异步方法的。
this.communicationServiceFake
.Setup(x => x.WriteParameterAsync(It.IsAny<string>(), It.IsAny<object>()))
.ReturnsAsyncIncomplete();
扩展 ReturnsAsyncIncomplete 不会在 await 关键字处立即返回,基本上类似于此处找到的内容:Async/Await and code coverage
我使用自己的 TaskSheduler 来确保方法在 Task.Factory.StartNew 返回之前竞争。
Task.Factory.StartNew(() => viewModel.Command.Execute(null),
CancellationToken.None, TaskCreationOptions.None, new CurrentThreadTaskScheduler ());
基本上,CurrentThreadTaskScheduler 来自这里:Wait until all Task finish in unit test,看起来像这样:
public class CurrentThreadTaskScheduler : TaskScheduler
{
protected override void QueueTask(Task task)
{
this.TryExecuteTask(task);
}
protected override bool TryExecuteTaskInline(Task task, bool wasPreviouslyQueued)
{
return this.TryExecuteTask(task);
}
protected override IEnumerable<Task> GetScheduledTasks()
{
yield break;
}
}
命令确实调用了以下代码:
await this.communicationService.WriteParameterAsync("Parameter1", true);
await this.communicationService.WriteParameterAsync("Parameter2", true);
然后验证:
this.communicationServiceFake
.Verify(t => t.WriteParameterAsync("Parameter1", true), Times.Once);
this.communicationServiceFake
.Verify(t => t.WriteParameterAsync("Parameter2", true), Times.Once);
有时它会说第二次通话没有发生。 如果我用 ThreadSleep 替换我的 Task.Factory.StartNew 以确保一切都完成,即使它确实注意到不必要地延迟我的单元测试似乎是正确的,但一切正常。
为什么我的 CurrentThreadTaskScheduler 允许 Task.Factory.StartNew 在我的 Command.Execute 完成之前返回?
【问题讨论】:
-
我似乎完全不明白你为什么需要使用
StartNew? -
如果我只使用 viewModel.Command.Execute,Command.Execute 在后台有一些未完成的触发和忘记任务,这是尝试使用客户任务等待这些触发并忘记任务调度器。遗憾的是它没有按预期工作。
标签: c# unit-testing task-parallel-library async-await