将System类作为构造函数参数传递

时间:2010-04-16 12:30:56

标签: c# tdd mocking

这可能很疯狂。

我想把依赖注入的想法变为极端。我已将所有与System.IO相关的行为隔离到一个类中,这样我就可以在其他类中模拟该类,从而减轻了我对更大的单元测试套件担心实际文件系统的负担。

但是我最终得到的File IO类只能通过集成测试进行测试,当然 - 这会引入我真正想要处理的复杂性并不是我想要做的就是确保我的FileIO class调用正确的System.IO东西。我不需要集成测试System.IO。我的FileIO类不仅仅是简单地包装System.IO函数,它不时地包含一些逻辑(也许这就是问题?)。

所以我想要的是能够测试我的File IO类,以确保它通过模拟System.IO类本身来进行正确的系统调用。理想情况下,这就像拥有像这样的构造函数一样简单:

    public FileIO(
        System.IO.Directory directory, 
        System.IO.File file, 
        System.IO.FileStream fileStream
    )
    {
        this.Directory = directory;
        this.File = file;
        this.FileStream = fileStream;
    }

然后调用类似的方法:

    public GetFilesInFolder(string folderPath)
    {
        return this.Directory.GetFiles(folderPath)
    }

但是由于所讨论的System.IO类是静态类,因此不会出现这种情况。据我所知,他们既不能以这种方式实例化,也不能用于嘲弄的目的。

2 个答案:

答案 0 :(得分:5)

创建一个包含简单重定向到System.IO的函数的类。创建另一个伪造/模拟System.IO的类。让这两个类都实现一个通用接口。然后你不必担心System.IO充满静态的事实。

答案 1 :(得分:1)

每当您想要保护自己免受设计中不需要的框架内部内容时,只需根据需要编写理想的界面即可。这意味着,如果您只需要File.Exists(),File.Delete()和File.OpenRead(),那么请编写一个只有您实际需要的这些方法的简单接口。

之后,您将围绕实现您的接口的实际框架实现编写一个包装类,并成功隐藏您试图摆脱的框架goo。

我在无点项目上完成了这项工作,其中包含大多数通过静态变量访问的HttpContext内容。你可以在这里看到一个例子:

http://github.com/dotless/dotless/blob/master/src/dotless.Core/Abstractions/IResponse.cs

IResponse是我简单的界面,完全符合我的需要。 CssResponse中的代码可以通过集成测试进行测试,但是现在我只是认为它可以工作,因为我从来没有碰过它,而且相当简单。每当我需要使用IResponse接口测试一个类时,我只需要注入一个模拟对象或假的。

问候丹尼尔