C# 对 async void 方法进行单元测试

假设需要对某个 async void 方法进行单元测试。

停止吧!

相对于解决这个问题,竭尽全力避免它才是更应该做的。如果能把 async void 方法改成 async Task 方法,那就再好不过了。

在一些情况下,比如为了满足接口方法签名,某个方法必须是 async void,那么可以考虑编写两个方法:包含所有逻辑的 async Task 方法,以及调用 async Task 方法并等待结果的 async void 包装。async void 方法能满足架构需求,async Task 方法(包含所有逻辑)则是可以测试的。

如果无法更改方法,而又必须对 async void 方法进行单元测试,也是有办法的。可以使用 Nito.AsyncEx 库中的 AsyncContext 类型:

// 此解决方案并非推荐方案,请阅读完本节的剩余内容
    [TestMethod]
    public void MyMethodAsync_DoesNotThrow()
    {
        AsyncContext.Run(() =>
        {
            var objectUnderTest = new Sut();
            objectUnderTest.MyVoidMethodAsync();
        });
    }

AsyncContext 类型会保持等待状态,直到所有异步操作完成(包括 async void 方法),并会传递被抛出的异常。

可以在 Nito.AsyncEx NuGet 包中获取 AsyncContext 类型。

对于 async 代码,一条关键准则是避免 async void。强烈建议重构代码,而不是使用 AsyncContext 来对 async void 方法进行单元测试。

 (完)

相关阅读:


C# 对 async 方法进行单元测试

C# 对预期失败的 async 方法进行单元测试

C# 对 async void 方法进行单元测试

C# 对数据流网格进行单元测试

C# 对 System.Reactive 可观察对象进行单元测试

C# 通过伪造调度对 System.Reactive 可观察对象进行单元测试

评论

此博客中的热门博文

in 参数(C# 7.2)

C# ref 局部变量和 ref return

类 ref 结构体(C# 7.2)