以下是该方案:
我有一个通过FileStream和.NET中的StreamReader读取文件的方法。我想单元测试这个方法,并以某种方式删除对StreamReader对象的依赖。
理想情况下,我希望能够提供自己的测试数据字符串,而不是使用真实文件。现在,该方法始终使用StreamReader.ReadLine方法。为了使这个测试成为可能,我现在修改设计的方法是什么?
答案 0 :(得分:11)
取决于Stream
和TextReader
。然后,您的单元测试可以使用MemoryStream
和StringReader
。 (或者,如果需要,可以从测试程序集内部加载资源。)
请注意TextReader
最初声明ReadLine
的原因,不是 StreamReader
。
答案 1 :(得分:3)
最简单的解决方案是让方法接受Stream作为参数,而不是打开自己的FileStream。您的实际代码可以像往常一样传入FileStream,而您的测试方法可以使用不同的FileStream来测试数据,也可以使用MemoryStream填充您想要测试的内容(不需要文件)。
答案 2 :(得分:2)
我认为这是调查Dependency Injection优点的绝佳机会。
您可能需要考虑重新设计方法,以便它需要一个返回文件内容的委托。一个委托(生产者)可能使用System.IO中的类,而第二个委托(用于单元测试)直接将内容作为字符串返回。
答案 3 :(得分:0)
我认为这个想法是依赖注入TextReader并模拟它进行单元测试。我认为你只能模拟TextReader,因为它是一个抽象类。
public class FileParser
{
private readonly TextReader _textReader;
public FileParser(TextReader reader)
{
_textReader = reader;
}
public List<TradeInfo> ProcessFile()
{
var rows = _textReader.ReadLine().Split(new[] { ',' }).Take(4);
return FeedMapper(rows.ToList());
}
private List<TradeInfo> FeedMapper(List<String> rows)
{
var row = rows.Take(4).ToList();
var trades = new List<TradeInfo>();
trades.Add(new TradeInfo { TradeId = row[0], FutureValue = Convert.ToInt32(row[1]), NotionalValue = Convert.ToInt32(row[3]), PresentValue = Convert.ToInt32(row[2]) });
return trades;
}
}
然后使用Rhino Mock模拟
public class UnitTest1
{
[Test]
public void Test_Extract_First_Row_Mocked()
{
//Arrange
List<TradeInfo> listExpected = new List<TradeInfo>();
var tradeInfo = new TradeInfo() { TradeId = "0453", FutureValue = 2000000, PresentValue = 3000000, NotionalValue = 400000 };
listExpected.Add(tradeInfo);
var textReader = MockRepository.GenerateMock<TextReader>();
textReader.Expect(tr => tr.ReadLine()).Return("0453, 2000000, 3000000, 400000");
var fileParser = new FileParser(textReader);
var list = fileParser.ProcessFile();
listExpected.ShouldAllBeEquivalentTo(list);
}
}
但问题在于,从客户端代码传递这样一个对象是否是一个好习惯,而我觉得它应该在负责处理的类中使用。我同意将sep委托用于实际代码的想法和一个用于单元测试的想法,但这又是生产中的一些额外代码。我可能有点迷失依赖注入和模拟甚至文件IO打开/读取的想法实际上不是单元测试的候选者,但文件处理逻辑可以通过传递文件的字符串内容来测试( AAA23 ^ ^ YKL890 ^ 300000 TTRFGYUBARC)。
请有任何想法!感谢