mmu*_*lva 13 c# synchronization unit-testing asynchronous task
我有这个课我要单元测试:
public class SomeClass
{
    public void Foo()
    {
        Bar();
    }
    private void Bar()
    {
        Task.Factory.StartNew(() =>
        {
            // Do something that takes some time (e.g. an HTTP request)
        });
    }
}
这就是我的单元测试的样子:
[TestMethod]
public void TestFoo()
{
    // Arrange
    var obj = new SomeClass();
    // Act
    obj.Foo();
    obj.Foo();
    obj.Foo();
    // Assert
    /* I need something to wait on all tasks to finish */
    Assert.IsTrue(...);
}
所以,我需要让单元测试线程等到Bar方法中启动的所有任务都完成了他们的工作,然后再开始我的断言.
重要提示:我无法改变SomeClass
我怎样才能做到这一点?
Dou*_*las 25
解决此问题的一种方法是以这样一种方式定义您自己的任务调度程序,以便您可以跟踪嵌套任务的完成情况.例如,您可以定义一个同步执行任务的调度程序,如下所示:
class SynchronousTaskScheduler : 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;
    }
}
随后,创建此同步任务调度程序的实例,并使用它来执行根任务,从而生成所有"隐藏"任务.由于嵌套任务从其父级继承当前任务调度程序,因此所有内部任务也将在我们的同步调度程序上运行,这意味着我们的最外层StartNew调用只会在所有任务完成时返回.
TaskScheduler scheduler = new SynchronousTaskScheduler();
Task.Factory.StartNew(() =>
{
    // Arrange
    var obj = new SomeClass();
    // Act
    obj.Foo();
    obj.Foo();
    obj.Foo();
}, 
    CancellationToken.None,
    TaskCreationOptions.None,
    scheduler);
// Assert
/* I need something to wait on all tasks to finish */
Assert.IsTrue(...);
这种方法的缺点是你将失去你的任务的所有并发性; 但是,您可以通过将自定义调度程序增强为并发调度程序但仍允许您跟踪执行任务来解决此问题.
Task.WaitAll(the, list, of, task, objects, you, need, to, wait, on);
如果这是一种void async方法,那么您将无法做到。设计已损坏。他们只是为了生火而忘却。
| 归档时间: | 
 | 
| 查看次数: | 11458 次 | 
| 最近记录: |