C# 如何编写测试以公开从使用块返回的任务?
我编写了以下错误异步方法,该方法通过了单元测试,但在生产中失败(EDIT:在生产中,它抛出了一个C# 如何编写测试以公开从使用块返回的任务?,c#,unit-testing,async-await,C#,Unit Testing,Async Await,我编写了以下错误异步方法,该方法通过了单元测试,但在生产中失败(EDIT:在生产中,它抛出了一个ObjectDisposedException): 我的问题是:我如何编写一个单元测试,该测试在错误版本的代码中可靠地失败? 编辑:以下是当前(不足的)单元测试,它没有暴露此问题: [Test] public async Task GivenFileUtilsWhenReadAllTextThenGetsText() { var file
ObjectDisposedException
):
我的问题是:我如何编写一个单元测试,该测试在错误版本的代码中可靠地失败?
编辑:以下是当前(不足的)单元测试,它没有暴露此问题:
[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);
}
问题是,您没有在文件中放入足够的内容,从而导致在异步读取时释放该文件 因此,这并不是说您的代码是同步执行的。它完成任务的速度太快,导致生产中出现问题 为了证明这一点,我只是添加了更多的内容
for (int i = 0; i < 10; i++) { expected += expected; }
for(inti=0;i<10;i++){expected+=expected;}
在写入文件并运行测试之前
var fileUtils = new FileUtils(); // the prod code above is in class FileUtils
var path = @"foo.txt";
var expected = "foo";
for (int i = 0; i < 15; i++) {
expected += expected;
}
File.WriteAllText(path, expected);
var text = await fileUtils.ReadAllText(path);
text.Should().Be(expected);
var fileUtils=new fileUtils();//上面的产品代码位于FileUtils类中
var path=@“foo.txt”;
var expected=“foo”;
对于(int i=0;i<15;i++){
预期+=预期;
}
File.WriteAllText(路径,应为);
var text=await fileUtils.ReadAllText(路径);
text.Should().Be(应为);
确实,对象处理异常导致测试失败
通过使用块在中等待,您已经找到了问题代码的解决方案
编写测试来发现您所寻找的内容将是相当困难的,但是代码分析器在编译时发现此类错误的机会会更大
我该如何编写一个单元测试,它会因为错误版本的代码而可靠地失败
根据需求来构建它。这是您要测试的内容:
“SUT不应立即处理流。它可以在流被完全读取后处理流。”
为此,您的单元测试需要控制:
正在处理的流,因此它可以检测何时发生处理
当流被完全读取时
这两个都可以使用自定义流类型来处理
对于第一个存根需求,当调用Dispose
时,自定义流类型可以将bool Disposed
属性设置为true
对于第二个存根需求,您的自定义流类型可以实现为仅在接收到信号后完成异步操作。“异步信号”的一种类型是TaskCompletionSource
——您可以在自定义流中创建实例,让每个async
方法wait
其Task
属性,当您的单元测试准备好让流完成时,它可以很好地完成TaskCompletionSource
,不一定,尽管那很好。我只是想让单元测试失败。这个问题更新得很好。正在审阅。Ok运行了一些测试。你的代码很好。问题是,您没有在文件中放入足够的内容以使其被释放。它完成得太快了。在写入文件并运行测试之前,我刚刚为(int i=0;i<10;i++){expected+=expected;}
添加了更多内容,并确保有足够的对象处理异常。这是一个选项吗?将整个方法替换为System.IO.File.ReadAllTextAsync(path)
。现在它不是你的代码,你也不必为它编写测试。那么就让内容变长吧?但它仍然不能保证失败,对吗?这种方法总是依赖于系统的,看起来这个测试确实证明了原始代码在失败的测试中是有缺陷的。这将需要重构SUT才能操作流。考虑到当前代码的紧密耦合,这是我看到它被完成的唯一方式。SUT是什么?SUT=测试中的系统。在本例中,FileUtils.ReadAllText
。
for (int i = 0; i < 10; i++) { expected += expected; }
var fileUtils = new FileUtils(); // the prod code above is in class FileUtils
var path = @"foo.txt";
var expected = "foo";
for (int i = 0; i < 15; i++) {
expected += expected;
}
File.WriteAllText(path, expected);
var text = await fileUtils.ReadAllText(path);
text.Should().Be(expected);