如何从测试项目同步 运行 方法(无等待)

How to run method synchronously from test project (no await)

我对使用 Task 和围绕它的整个概念还很陌生。我还使用 Net 4.0Office 2007 的 VSTO 开发

我想了解我在我的应用程序中写的一件事,它正在生产中工作,但为它编写单元测试最终使用 Thread.Sleep 并检查任务是否 运行 完成或不是

背景

生产代码非常简单,它调用一个服务来检查环境状态(PROD、STAGE、QA 等)它在(void) 方法通过 Task,在任务体内它设置了一个正在更新 UI (WPF) 的 属性 并且它工作正常。请注意,我没有在该方法中使用 Wait 。如果任务失败,我将继续执行另一个 OnlyOnFaulted

问题

我尝试对方法进行单元测试 (void) 所以我想 运行 方法 运行ning 同步 但我失败了那里。 我读到 RunSynchronously,也看到有人使用任务。Result4.0 似乎不可用), 也试过 Scheduler.Current, AttachedToParent 等等

我认为问题出在我的设计上,我想我正在尝试调用一个方法并说 "Hey, run synchronously" 它确实如此,但在方法内部是另一个 运行 async 的任务所以不管它总是 运行 异步的。我对吗?有没有办法在我的测试项目中没有循环并等待 RunToCompletion?

来测试它

这是我为了更好地理解而创建的示例代码,我对其进行了一些简化。在实际实施中,我的解决方案中有一个适当的测试项目,我正在模拟该服务,因此它不会调用真实的服务等。

namespace ConsoleApplication1
{
public class Program
{
    static void Main(string[] args)
    {
        ImagineThisIsInTestProject();
        Console.ReadLine();

        Console.WriteLine("Started");
        var cls = new Program();
        cls.MyProdMethod();
        Console.WriteLine("Finished");
        Console.ReadLine();
    }

    public string Status { get; private set; }

    public void MyProdMethod()
    {
        // I have more logic in my real method, serialization, handling errors
        Console.WriteLine("In my method");
        var task = Task.Factory.StartNew(() => {
                        Thread.Sleep(2000);
                        Console.WriteLine("Setting status");
                        Status = "Yes I set it";
                        }, CancellationToken.None);
        Console.WriteLine("Finishing my method");
    }

    public static void ImagineThisIsInTestProject()
    {
        Console.WriteLine("TEST started");
        var sut = new Program();
        var task = new Task(() => sut.MyProdMethod());
        task.RunSynchronously(); // I would assume this will wait until the task is finished?

        // here my assert if status is set
        Console.WriteLine($"Status is - {sut.Status}");
        Console.WriteLine("TEST finished");
    }
}
}

上面的输出是

TEST started
In my method
Finishing my method
Status is -
TEST finished
Setting status

Started
In my method
Finishing my method
Finished
Setting status

您无法真正测试您的方法 public void MyProdMethod() 因为:

var task = Task.Factory.StartNew(() => {
                    Thread.Sleep(2000);
                    Console.WriteLine("Setting status");
                    Status = "Yes I set it";
                    }, CancellationToken.None);

基本上是一火就忘了

除非您等待任务完成,否则无法对此进行测试。我知道您不想包含 Wait 但要测试请考虑以下内容:

    public void MyProdMethod()
    {
        // I have more logic in my real method, serialization, handling errors
        Console.WriteLine("In my method");
        Task.Factory.StartNew(() => {
            Thread.Sleep(2000);
            Console.WriteLine("Setting status");
            Status = "Yes I set it";
        }, CancellationToken.None).Wait();

        Console.WriteLine("Finishing my method");
    }

然后您的测试将如下所示:

[TestClass]
public class TestClass
{
    [TestMethod]
    public void Test()
    {
        // Arrange
        var program = new Program();

        // Act
        program.MyProdMethod();

        // Assert
        Assert.AreEqual("Yes I set it", program.Status);
    }

}

如果您退出 Wait,测试将在方法中的任务有机会完成之前完成,因此导致断言失败。