需要:.NET中的文件系统接口和实现

时间:2009-03-19 22:15:55

标签: .net unit-testing file-io dependency-injection mocking

  

可能重复:
  How do you mock out the file system in C# for unit testing?

我将单元测试写入我的代码,使用Moq作为模拟框架 我的代码包括使用对System.IO类的直接调用对文件系统的调用。例如,File.Exists(...)等 我想将该代码更改为更易测试,因此我应该使用相关方法(例如IFile)来说明Exists(string path)。 我知道我可以从头开始编写它,但我认为可能有一个完整,健壮的框架,它具有文件系统的接口和实现。这个(期望的)框架也可以是某种“服务”,因此它的API不必是System.IO命名空间的“接口等效”。
请注意,我真的希望有接口(和不是静态方法),以便我的代码可以用于依赖注入

到目前为止我得到了什么:

  • 有点类似,但在stackoverflow中询问了not the same question
  • codeplex.com中有一个名为 CodePlex源代码管理客户端link)的项目,在源代码中包含此类(请参阅源代码中的/Source/TfsLibrary/Utility/具体细节)

还有其他建议吗?

6 个答案:

答案 0 :(得分:6)

I've written adapters用于静态System.IO.FileDirectory方法。然后在我的课程中,我做了以下几点:

public class MyService {
  public IFile File {private get;set;}
  public MyService() {
    File = new FileImpl();
  }
  public void DoSomething() {
    File.ReadAllText("somefile");
  }
}

然后你可以注入一个模拟作为IFile进行测试。

答案 1 :(得分:5)

好吧,我没有你想要的文件系统模拟库(虽然它可能在某处并且会很酷),但这可能有所帮助。单元测试思想的“行为主义”学派提出的一个有趣的概念是“外向接口”的概念。在某些情况下,将对象调用到自身之外的整个事物中并将它们转换为接口似乎具有同样多的价值,就像在外部为方法创建接口的典型行为一样世界可以在您的对象上调用

在这种情况下,您可以考虑,而不是模拟整个文件系统,为您的对象需要的外部世界的答案和服务创建一个或多个逻辑上一致的接口。这些电话只会回答您需要回答的问题......而不是规定实施。然后,您可以使用您提到的依赖注入来注入您希望进行测试的实现。而且你可能会使用Moq这样做,因为你熟悉它。

因此,您的“传出接口”可能有一个名为DoesFileExist()的方法。它可能接受一条路径。或者,如果您的对象尝试回答“更高级别”的业务问题,并且查看文件是否存在仅仅方式该问题已得到解答,那么您的传出接口可能没有方法关于文件存在。它可能是“DoIAppearToHaveAccessToTheFileServer”,甚至是“IsThereAPreviouslySavedGame”。

这是一些工作,但可能更符合良好单元测试的原则...让你的测试对象表达它想要做的事情,并让你的单元测试它并且只测试它。只是一个想法...希望它有所帮助。

答案 2 :(得分:3)

我在CodePlex上维护Jolt.NET项目,该项目包含一个库,可以为您生成此类接口及其实现。有关详细信息,请参阅Jolt.Testing库。

答案 3 :(得分:2)

http://systemwrapper.codeplex.com/提供了很好的选择,虽然我还没有尝试过。看起来作者可以在完成项目时使用一些帮助。

答案 4 :(得分:0)

我知道Typemock包可以做这样的事情。

答案 5 :(得分:-1)

我不是模拟文件系统接口,而是传统上选择模拟Filesystem本身。对于任何严肃的操作系统来说,这都是相对容易的您可以使用Mono.FuseFUSE的C#实现,USErspace中的文件系统,轻松构建用户空间文件系统。我不确定如果要获得Dokan,FUSE for Windows需要移植,但FUSE在Linux,OSX和Solaris上运行良好。