繁体   English   中英

在单元测试中同步调用异步方法是不正确的吗?

[英]Is it incorrect to call async methods synchronously in unit tests?

我是async / await世界的新手,我正在试图找出为异步方法编写异步单元测试的好处。 也就是说,异步方法的单元测试是否必须异步调用异步方法? 如果它使用Task.Run()同步调用异步方法,会丢失什么? 在后一种情况下,代码覆盖范围不会受到影响,据我所见。

我问这个的原因是因为我们的模拟软件(我们使用TypeMock)不能支持async / await。 他们说这是缺乏支持的合理原因 ,我并不反对他们。)通过在单元测试中同步调用异步方法,我们可以解决这个问题。 但是,我想通过这样做来了解我们是否正在削减任何角落。

例如,假设我有以下异步方法:

public async Task<string> GetContentAsync(string source)
{
    string result = "";
    // perform magical async IO bound work here to populate result
    return result;
}

以下是不起作用的理想单元测试:

[TestMethod()]
public async Task GetContentAsyncTest()
{
    string expected = "thisworks";
    var worker = new Worker();
    // ...mocking code here that doesn't work!
    string actual = await worker.GetContentAsync();
    Assert.AreEqual(expected, actual);
}

但这很有效,它确实提供了我们需要的代码覆盖率。 这个可以吗?

[TestMethod()]
public void GetContentAsyncTest()
{
    string expected = "thisworks";
    var worker = new Worker();
    // mocking code here that works!
    string actual = Task.Run(() => worker.GetContentAsync()).Result;
    Assert.AreEqual(expected, actual);
}

必须对异步方法进行单元测试,异步调用async方法吗?

不,但这样做是最自然的。

如果它使用Task.Run()同步调用异步方法,会丢失什么?

真的没什么。 它的性能稍差,但在某种程度上你可能永远不会注意到。

您可能希望使用GetAwaiter().GetResult()而不是Result来避免失败测试中的AggregateException包装。 你也可以直接调用这个方法; 无需将其包装在Task.Run

他们说这种缺乏支持是有正当理由的,我并不反对。

哦,我当然不同意他们。 :)

这是否意味着他们无法对迭代器块进行单元测试? 完全相同的推理将适用......


不支持async单元测试的唯一更严重的问题是,如果被测代码假定其上下文将处理同步。 这很常见,例如,在中等复杂的View模型中。

在这种情况下,您需要安装一个执行async代码的上下文(例如,我的AsyncContext类型 ),除非您使用自动提供一个的单元测试框架(截至本文撰写时,只有xUnit执行AFAIK) 。

如果您使用xUnit而不是MSTest,那么您的理想解决方案(异步测试)将起作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM