异步单元测试 - async/await 与 Task.Result

Asynchronous Unit Testing - async/await vs. Task.Result

我和我的解决方案架构师正在讨论对异步代码进行单元测试的正确方法。

他更喜欢使用void [Test]方法,断言Task.Result,而我觉得异步方法应该用async/await [Test]方法进行测试。

不知何故,我觉得使用 Task.Result 是测试异步代码的不正确方法,但无法证明或指出确切原因?

例如,给定以下代码:

    public class SomeService 
    {
        public async Task<bool> ProcessSomething(string request)
        {
           return await Repository.Save(request);
        }
    }

方法一:Task.Result

    [Test]
    public void ServiceProcessTest()
    {          
       var sut = new SomeService();

       // Use Task.Result
       var unusedResult= sut.ProcessSomething("Hello world!").Result;
       
       A.CallTo(() => Repository.Save(A<string>>.Ignored)).MustHaveHappenedOnceExactly();
    }

方法二:async/await

    [Test]
    public async Task ServiceProcessTest()
    {          
       var sut = new SomeService();

       // Use async/await
       var unusedResult= await sut.ProcessSomething("Hello world!");
       
       A.CallTo(() => Repository.Save(A<string>>.Ignored)).MustHaveHappenedOnceExactly();
    }

我们应该使用哪一次,为什么? 如果两者都是正确的,那么有时一个比另一个更受欢迎吗?

正如其他人在评论中指出的那样,如果可以,请始终使用 async/await,因为 Task.Result can cause deadlocks。此外,单元测试应反映您如何使用生产代码中的 System Under Test (SUT)。

你应该使用 Task.Result IMO 的 只有 情况是引入一个 function/object 那 returns 一个 Task 遗留代码 中并且您(还)不能创建调用方法 async,因此您不得不使用 Task.Result 来执行 Task.