gpt4 book ai didi

c# - 如何编写测试以公开从 using block 返回任务?

转载 作者:太空宇宙 更新时间:2023-11-03 12:01:37 24 4
gpt4 key购买 nike

我编写了以下有问题的异步方法,它通过了单元测试但在生产中失败(编辑:在生产中它抛出一个 ObjectDisposedException):

public class FileUtils {
public Task<string> ReadAllText(string path)
{
using (var stream = ReadStreamAsync(path))
using (var reader = new StreamReader(stream))
{
return reader.ReadToEndAsync();
}
}

private static FileStream ReadStreamAsync(string path)
{
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read,
4096, FileOptions.Asynchronous);
}
}

错误是,如果您从 using block 中返回一个任务,则该代码仅在 ReadToEndAsync 调用恰好同步执行(这显然发生在我的单元测试)。

正确的代码添加asyncawait如下:

    public async Task<string> ReadAllText(string path)
{
using (var stream = ReadStreamAsync(path))
using (var reader = new StreamReader(stream))
{
return await reader.ReadToEndAsync();
}
}

我的问题是:我该如何编写一个单元测试,它会因代码的不正确版本而可靠地失败?

编辑:这是未暴露此问题的当前(不充分)单元测试:

    [Test]
public async Task GivenFileUtilsWhenReadAllTextThenGetsText()
{
var fileUtils = new FileUtils(); // the prod code above is in class FileUtils
var path = @"C:\tmp\foo.txt";
var expected = "foo";
File.WriteAllText(path, expected);

var text = await fileUtils.ReadAllText(path);

text.Should().Be(expected);
}

最佳答案

How would I write a unit test that would reliably fail for the incorrect version of the code?

根据要求构建它。这是您要测试的内容:

“SUT 不应立即处理流。它可能会在流被完全读取后处理流。”

为此,您的单元测试需要控制:

  1. 正在处理的流,因此它可以检测何时发生处理。
  2. 当流被完全读取时。

这两者都可以使用自定义流类型来处理。

对于第一个 stub 要求,您的自定义流类型可以只有一个 bool Disposed设置为 true 的属性什么时候Dispose被称为。

对于第二个 stub 要求,您的自定义流类型可以实现为仅在收到信号后完成异步操作。 “异步信号”的一种类型是 TaskCompletionSource<T> - 您可以在自定义流中创建实例,每个 async方法 await它的Task属性,当您的单元测试准备好让流完成时,它可以完成 TaskCompletionSource<T> .

关于c# - 如何编写测试以公开从 using block 返回任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56780800/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com