如何使用.Net IO类创建可测试代码
本文关键字:测试 代码 创建 何使用 Net IO | 更新日期: 2023-09-27 18:19:37
我想创建单元可测试代码,模拟对.Net System.IO类的调用,这样我就可以真正进行单元测试,而不是依赖于文件系统。我正在使用SystemWrapper类来包装BCL类。
我试图得到一个简单的例子,看看是否存在一个文件。
我遇到的问题是,在类中注入依赖项不起作用,因为实例化依赖项(通过StructureMap)需要知道要传递什么构造函数参数,而这在当时是不可用的,而且没有默认的构造函数。
示例代码:
// don't want to create dependency here like so
//IFileInfoWrap fileInfoWrap = new FileInfoWrap(filename);
// using service locator (anti-pattern?!) since it can't be
// injected in this class
var fileInfoWrap = ObjectFactory.GetInstance<IFileInfoWrap>(
new ExplicitArguments(new Dictionary<string, object>
{
{"fileName", filename}
}));
Console.WriteLine("File exists? {0}", fileInfoWrap.Exists);
我不喜欢的是没有注入依赖项,ObjectFactory不应该在这里(但我看不到其他创建方法)。ExplicitArguments使它变得混乱,并且参数名称是一个神奇的字符串。
为了让它发挥作用,StructureMap配置类需要明确我想使用哪个构造函数(我刚开始使用StructureMap,所以这可能不是正确的设置方式):
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
scan.AssembliesFromPath(".");
scan.RegisterConcreteTypesAgainstTheFirstInterface();
scan.WithDefaultConventions();
});
// use the correct constructor (string instead of FileInfo)
x.SelectConstructor(() => new FileInfoWrap(null as string));
// setting the value of the constructor
x.For<IFileInfoWrap>()
.Use<FileInfoWrap>()
.Ctor<string>("fileName")
.Is(@".");
});
有人找到更好的解决方案来针对System.IO类创建可测试代码吗?我知道问题的一部分在于System.IO类的设计。
我成功使用的一种方法是为System.IO
和FCL的其他部分中找到的类型滚动我自己的代理类型。例如,我想对System.IO.File
进行依赖。我创建了一个名为System.IO.Proxies
的库,并添加了一个具体类型File
和一个接口IFile
。接口IFile
公开了与我从System.IO.File
中需要的所有成员等价的成员,而具体类型只通过将方法调用转发到System.IO.File
来实现这些成员。System.IO.Proxies
被排除在单元测试和代码覆盖范围之外。在我的消费程序集中,我只接受System.IO.Proxies
的依赖项,特别是,我只对IFile
的依赖项。通过这种方式,我可以轻松地模拟这种依赖关系,并为我的消费程序集实现100%的代码覆盖率。
(注意,这是我对上一个问题的更一般的回答的定制版本。)