【发布时间】:2012-02-04 19:56:55
【问题描述】:
我想创建可单元测试的代码来模拟对 .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 类的设计。
【问题讨论】:
-
SystemWrapper 包含大部分非常容易泄漏的抽象。对 Streams、TextWriter、TextReader 等进行 IO 建模会更加简单和容易。这些类已经是抽象的,完全不需要 SystemWrapper。
-
对流的另一票
-
我对 SystemWrapper 的发现是,它似乎是一个很好的接口包装器,但由于原始类的工作方式,它仍然是一个死胡同。例如,无法正确模拟返回 FileInfo 对象数组。滚动我自己的更简化的包装器,它不必模仿现有的类,而更多的工作确实会导致一个可行的解决方案恕我直言。
标签: c# dependency-injection tdd inversion-of-control base-class-library