摆脱单元测试对 StreamReader/FileStream 的依赖的好方法是什么?
场景如下:
我有一个通过 .NET 中的 FileStream 和 StreamReader 读取文件的方法。我想对这个方法进行单元测试,并以某种方式删除对 StreamReader 对象的依赖。
理想情况下,我希望能够提供自己的测试数据字符串,而不是使用真实的文件。现在,该方法始终使用 StreamReader.ReadLine 方法。为了使这个测试成为可能,修改我现在的设计的方法是什么?
Here's the scenario:
I have a method that reads in a file via a FileStream and a StreamReader in .NET. I would like to unit test this method and somehow remove the dependency on the StreamReader object.
Ideally I would like to be able to supply my own string of test data instead of using a real file. Right now the method makes use of the StreamReader.ReadLine method throughout. What is an approach to modifying the design I have now in order to make this test possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
而是依赖于
Stream
和TextReader
。然后您的单元测试可以使用MemoryStream
和StringReader
。 (或者如有必要,从测试程序集中加载资源。)请注意
ReadLine
最初是由TextReader
声明的,不是StreamReader
声明的。Depend on
Stream
andTextReader
instead. Then your unit tests can useMemoryStream
andStringReader
. (Or load resources from inside your test assembly if necessary.)Note how
ReadLine
is originally declared byTextReader
, notStreamReader
.最简单的解决方案是让该方法接受 Stream 作为参数,而不是打开自己的 FileStream。您的实际代码可以像往常一样传入 FileStream,而您的测试方法可以使用不同的 FileStream 来测试数据,或者使用您想要测试的内容填充 MemoryStream(不需要文件)。
The simplest solution would be to have the method accept a Stream as a parameter instead of opening its own FileStream. Your actual code could pass in the FileStream as usual, while your test method could either use a different FileStream for test data, or a MemoryStream filled up with what you wanted to test (that wouldn't require a file).
我突然想到,这是一个很好的机会来研究依赖注入的优点。
您可能需要考虑重新设计您的方法,以便它采用返回文件内容的委托。一个委托(生产委托)可能使用 System.IO 中的类,而第二个委托(用于单元测试)则直接以字符串形式返回内容。
Off the top of my head, I'd say this is a great opportunity to investigate the merits of Dependency Injection.
You might want to consider redesigning your method so that it takes a delegate that returns the file's contents. One delegate (the production one) might use the classes in System.IO, while the second one (for unit testing), returns the contents directly as a string.
我认为这个想法是依赖注入 TextReader 并模拟它进行单元测试。我认为你只能模拟 TextReader 因为它是一个抽象类。
然后使用Rhino Mock进行Mock,
但问题在于从客户端代码传递这样的对象是否是一个好的做法,而不是我觉得它应该在负责处理的类中使用来管理。我同意使用 sep 委托来执行实际代码,并使用 sep 委托来进行单元测试,但这又是生产中的一些额外代码。我可能对依赖注入和模拟甚至文件 IO 打开/读取的想法有点迷失,这实际上不是单元测试的候选者,但文件处理逻辑可以通过仅传递文件的字符串内容来测试( AAA23^YKL890^300000^TTRFGYUBARC)。
任何想法请!谢谢
I think the idea is to dependency inject the TextReader and mock it for unit testing. I think you can only mock the TextReader because it is an abstract class.
and then Mock using Rhino Mock
BUT the question lies in the fact whether it is a good practice to pass such an object from the client code rather I feel it should be managed with using within the class responsible for processing. I agree with the idea of using a sep delegate for the actual code and one for the unit testing but again that is a bit of extra code in production. I may be a bit lost with the idea of dependency injection and mocking to even file IO open/read which actually is not a candidate for unit testing but the file processing logic is which can be tested by just passing the string content of the file (AAA23^YKL890^300000^TTRFGYUBARC).
Any ideas please! Thanks