【问题标题】:Asynchronous Unit Testing - async/await vs. Task.Result异步单元测试 - async/await 与 Task.Result
【发布时间】:2021-04-06 13:14:17
【问题描述】:

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

他更喜欢用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();
    }

方法二:异步/等待

    [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 会导致死锁
  • 与任何方法的任何方面一样,您应该以您使用它的方式对其进行测试,否则您的测试无法帮助您验证它在您关心的情况下是否能正常工作。如果您的测试测试的行为与您的生产代码使用的行为不同,那么这些测试不会增加任何价值。
  • @Nkosi:是的,我确实查看了 Microsoft 文档,但它并没有否认使用 Task.Result(或者我可能错过了它)。

标签: c# unit-testing asynchronous async-await nunit


【解决方案1】:

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

唯一您应该使用Task.Result IMO 的情况是在遗留代码中引入返回Task 的函数/对象时处于(尚未)调用方法async的位置,所以你不得不使用Task.Result来执行Task

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-24
    • 2023-03-29
    • 2018-01-06
    • 2014-12-10
    • 2015-03-19
    • 2015-11-21
    • 1970-01-01
    相关资源
    最近更新 更多