.net NET中的模拟文件方法(如File.Copy(“1.txt”和“2.txt”))

.net NET中的模拟文件方法(如File.Copy(“1.txt”和“2.txt”)),.net,unit-testing,mocking,.net,Unit Testing,Mocking,我们有一些调用File.Copy、File.Delete、File.Exists等的方法。我们如何在不影响文件系统的情况下测试这些方法 我认为自己是一个单元测试N0B,所以任何建议都是值得赞赏的。 < P>如果你绝对要这么做,那就是你的朋友。 我不能说我自己用过它,我会试着设计我的方法来代替它,但就我所知,它会完成我的工作。我会的。您必须创建一个接口和一个类来代理真实的对象,这样您就可以让Moq创建代理的一个实例(模拟实例)但这是测试这类事情的最佳方法。您可以使用模拟框架来实现这一点,它将创建文

我们有一些调用File.Copy、File.Delete、File.Exists等的方法。我们如何在不影响文件系统的情况下测试这些方法


我认为自己是一个单元测试N0B,所以任何建议都是值得赞赏的。

< P>如果你绝对要这么做,那就是你的朋友。
我不能说我自己用过它,我会试着设计我的方法来代替它,但就我所知,它会完成我的工作。

我会的。您必须创建一个接口和一个类来代理真实的对象,这样您就可以让Moq创建代理的一个实例(模拟实例)但这是测试这类事情的最佳方法。

您可以使用模拟框架来实现这一点,它将创建文件对象的假副本,您可以将文件插入测试系统中

我将推荐Rhino Mock。

公共界面IFile{
public interface IFile {
    void Copy(string source, string dest);
    void Delete(string fn);
    bool Exists(string fn);
}

public class FileImpl : IFile {
    public virtual void Copy(string source, string dest) { File.Copy(source, dest); }
    public virtual void Delete(string fn) { File.Delete(fn); }
    public virtual bool Exists(string fn) { return File.Exists(fn); }
}

[Test]
public void TestMySystemCalls() {
    var filesystem = new Moq.Mock<IFile>();
    var obj = new ClassUnderTest(filesystem);
    filesystem.Expect(fs => fs.Exists("MyFile.txt")).Return(true);
    obj.CheckIfFileExists(); // doesn't hit the underlying filesystem!!!
}
无效副本(字符串源、字符串目标); 无效删除(字符串fn); bool存在(字符串fn); } 公共类FileImpl:IFile{ 公共虚拟空副本(字符串源,字符串目标){File.Copy(源,目标);} 公共虚拟void Delete(字符串fn){File.Delete(fn);} 公共虚拟bool Exists(字符串fn){return File.Exists(fn);} } [测试] public void TestMySystemCalls(){ var filesystem=new Moq.Mock(); var obj=新类未测试(文件系统); Expect(fs=>fs.Exists(“MyFile.txt”)).Return(true); obj.CheckIfFileExists();//未命中底层文件系统!!! }
我倾向于在我的大多数项目中创建一个名为IFileController的接口,该接口上包含所有文件操作。它可以有基本的方法,再加上.NET framework没有提供的任何处理文件的方法

使用依赖项注入框架,您可以获得IFileController的实例,而不必确切知道它是什么类型,也可以使用它,而无需对框架类型进行模拟。这使得所有内容都更易于测试,而且作为一种奖励,您可以在根本不更改代码的情况下更改文件存储机制


另一方面,任何新开发人员都需要了解该接口,否则他们将直接使用.NET方法。

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

您如何设计解决方案?@bovium:不,这是一个商业产品。@Jim:限制它可能与文件系统交互的位置,并可能将文件系统交互封装在一个接口中。您可以为文件系统使用一个单例(并将其替换为test-icky,但不是很糟糕),也可以使用依赖项注入。但一般来说,尝试让大多数需要数据的地方以流、读卡器、写入器的形式获取/生成数据-除非确实需要,否则不要使任何文件特定,我发布了一个答案,说明了“围绕”静态类进行设计。实际上,平台应该用静态方法公开一个静态类,当我们进行OOP时,应该在接口上调用实例方法。因此,我们有时不得不花时间来弥合差距。是什么限制了您访问文件系统?@GREEF——据我所知,单元测试不应该访问文件系统、数据库或访问网络。我正在努力遵守这些规则。另外,请看@Jim:don't hit the filesystem“是一条可弯曲的规则。只要您能够确保文件系统设备是一致的,那么点击文件系统就可以了。确保其一致性可能只不过是测试目录上的一个还原脚本。没有文件对象。我们在这里讨论的是静态方法。你可以按照我的回答中的评论来设计你的解决方法,但它确实需要改变。