单元测试代码,使用Task.Factory.StartNew().ContinueWith()

Joh*_*las 13 c# nunit unit-testing moq task-parallel-library

所以我有一些代码

Task.Factory.StartNew(() => this.listener.Start()).ContinueWith(
                    (task) =>
                        {
                            if (task.IsCompleted)
                            {
                                this.status = WorkerStatus.Started;
                                this.RaiseStatusChanged();
                                this.LogInformationMessage("Worker Started.");
                            }
                        });
Run Code Online (Sandbox Code Playgroud)

当我测试时,我正在模拟所有依赖对象(namley this.listener.Start()).问题是测试在ContinueWith被调用之前完成执行.当我调试时,由于我单步执行代码的额外延迟,它被称为罚款.

那么我怎么能 - 从不同程序集中的测试代码 - 确保代码在我的测试遇到其断言之前运行?

我可以使用Thread.Sleep ......但这似乎是一种真正的hacky方式.

我想我正在寻找Thread.Join的Task版本.

max*_*mpa 2

考虑以下:

public class SomeClass
{
    public void Foo()
    {
        var a = new Random().Next();
    }
}

public class MyUnitTest
{
    public void MyTestMethod()
    {
        var target = new SomeClass();        
        target.Foo(); // What to assert, what is the result?..
    }
}
Run Code Online (Sandbox Code Playgroud)

分配给 的值是什么a?您无法判断,除非结果是在方法外部返回的Foo()(作为返回值、公共属性、事件等)。

“协调线程的操作以获得可预测的结果”的过程称为同步

对于您的情况,最简单的解决方案之一可能是返回Task类的实例并使用其Wait()方法:

var task = Task.Factory.StartNew(() => Method1())
    .ContinueWith(() => Method2());
Run Code Online (Sandbox Code Playgroud)

无需等待第一个任务,因为ContinueWith()会创建一个在目标任务完成时异步执行的延续(MSDN):

task.Wait();
Run Code Online (Sandbox Code Playgroud)

  • 我无权从我的测试中访问任务实例,并且宁愿不为此目的编写一个包装器(但也许我必须这样做)。 (3认同)