你如何模拟C#中的文件系统进行单元测试?

pup*_*eno 140 c# unit-testing mocking

是否有任何库或方法来模拟C#中的文件系统来编写单元测试?在我目前的情况下,我有方法检查某个文件是否存在并读取创建日期.我将来可能需要更多.

Mat*_*lls 144

编辑:安装NuGet包System.IO.Abstractions.

当最初接受此答案时,此包不存在.原始答案是根据以下历史背景提供的:

你可以通过创建一个接口来做到这一点:

interface IFileSystem {
    bool FileExists(string fileName);
    DateTime GetCreationDate(string fileName);
}
Run Code Online (Sandbox Code Playgroud)

并创建一个使用System.IO.File.Exists()等的"真实"实现.然后您可以使用模拟框架模拟此接口; 我推荐Moq.

编辑:有人在这样做,恳请张贴在线这里.

我已经使用这种方法在IClock接口中模拟DateTime.UtcNow(对于我们的测试来说真的非常有用,可以控制时间流!),更传统的是ISqlDataAccess接口.

另一种方法可能是使用TypeMock,这允许您拦截对类的调用并将其存根.然而,这确实需要花钱,并且需要安装在整个团队的PC和构建服务器上才能运行,而且,它显然不适用于System.IO.File,因为它不能存根mscorlib.

您也可以接受某些方法不可单元测试,并在单独的慢速运行集成/系统测试套件中测试它们.

  • 在我看来,创建一个像 Matt 在这里描述的界面是正确的方法。我什至编写了一个为您生成此类接口的工具,这在尝试模拟静态和/或密封类或非确定性方法(即时钟和随机数生成器)时非常有用。请参阅 http://jolt.codeplex.com 了解更多信息。 (2认同)
  • 我用过这个http://systemioabstractions.codeplex.com/的最好的图书馆 (2认同)

Bin*_*ier 79

Install-Package System.IO.Abstractions

这个虚构的库现在存在,有一个用于System.IO.Abstractions的NuGet包,它抽象出System.IO命名空间.

还有一组测试助手,System.IO.Abstractions.TestingHelpers - 在撰写本文时 - 仅部分实现,但是一个非常好的起点.

  • 我认为围绕这​​个已经构建的抽象标准化是最好的选择.从来没有听说过这个图书馆,所以非常感谢你们. (3认同)

Jos*_*eph 10

您可能需要构建一个合同来定义文件系统中需要的内容,然后围绕这些功能编写包装器.此时,您将能够模拟或删除实现.

例:

interface IFileWrapper { bool Exists(String filePath); }

class FileWrapper: IFileWrapper
{
    bool Exists(String filePath) { return File.Exists(filePath); }        
}

class FileWrapperStub: IFileWrapper
{
    bool Exists(String filePath) 
    { return (filePath == @"C:\myfilerocks.txt"); }
}
Run Code Online (Sandbox Code Playgroud)


小智 10

通过像这样使用System.IO.AbstractionsSystem.IO.Abstractions.TestingHelpers :

public class ManageFile {
   private readonly IFileSystem _fileSystem;
   public ManageFile(IFileSystem fileSystem){

      _fileSystem = fileSystem;
   }

   public bool FileExists(string filePath){}
       if(_fileSystem.File.Exists(filePath){
          return true;
       }
       return false;
   }
}
Run Code Online (Sandbox Code Playgroud)

在您的测试类中,您使用 MockFileSystem() 来模拟文件,并实例化 ManageFile,如下所示:

var mockFileSysteme = new MockFileSystem();
var mockFileData = new MockFileData("File content");
mockFileSysteme.AddFile(mockFilePath, mockFileData );
var manageFile = new ManageFile(mockFileSysteme);
Run Code Online (Sandbox Code Playgroud)


ade*_*l41 5

我的建议是使用http://systemwrapper.codeplex.com/, 因为它为System命名空间中最常用的类型提供了包装器