Я написал следующий ошибочный асинхронный метод, который проходит свой модульный тест, но не работает в рабочем режиме ( EDIT: в рабочем режиме он выдает 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
, код будет работать только в том случае, если вызов ReadToEndAsync
выполняется синхронно (что, очевидно, произошло в моем модульном тесте).
Правильный код добавляет async
и await
следующим образом:
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);
}