2011-04-18 101 views
1

假的目录,我想对于类似这样的代码创建单元测试:的.NET单元测试

foreach (string domainName in Directory.GetDirectories(server.Path)) 
{ 
    HandleDomainDirectory(session, server, domainName); 
} 

的问题是,我用我的代码System.IO.Directory类。 如何创建不依赖于我硬盘上的任何文件夹的测试方法。 换句话说,我该如何伪造“Directory.GetDirectories(server.Path)”的回应? (请注意,我确实控制了我的班级中的“服务器”对象,因此我可以给任何我想要的路径)

谢谢。

回答

0

我发现的最佳解决方案是使用Moles。代码非常具体,并且必须做非常具体的事情。用包装类包装它将是多余的。我需要包装类的唯一原因是为了编写测试。痣允许我写没有任何包装类的测试:)

1

你会注入一个包装类。

public class DirectoryFetcher 
{ 
    public virtual List<string> GetDirectoriesIn(string directory) 
    { 
      return Directory.GetDirectories(directory); 
    } 
} 

然后注入是:

foreach(string directory in _directoryFetcher.GetDirectoriesIn(server.Path)) 
{ 
    // Whatever 
} 

然后,您可以莫克那家伙在注入点(本例使用起订量,和构造器注入):

Mock<DirectoryFetcher> mockFetcher = new Mock<DirectoryFetcher>(); 

mockFetcher.Setup(x => x.GetDirectoriesIn("SomeDirectory")).Returns(new List<string> 
{ 
    "SampleDirectory1", 
    "SampleDirectory2" 
}); 

MyObjectToTest testObj = new MyObjectToTest(mockFetcher.Object); 

// Do Test 
1

不需要调用直接使用Directory.GetDirectories(server.Path),您可以使用一个方法创建一个接口,如IDirectoryResolver,该方法接受一个路径字符串并返回目录列表。包含上面代码的类将需要一个类型为IDirectoryResolver的属性或字段,它可以通过构造函数或setter注入。

对于您的产品代码,您将创建一个实现IDirectoryResolver接口的新类。该类可以在其接口方法的实现中使用Directory.GetDirectories方法。

对于单元测试,您可以创建一个MockDirectoryResolver类,该类实现IDirectoryResolver(或使用模拟库为接口创建模拟实例)。模拟实现可以做你需要的任何事情。

0

在与外部世界进行通信时,例如文件系统,数据库,Web服务等,在我建议之前,应该始终考虑使用类似其他类的包装类。可测试性是一个主要论点,但更大的一个是:外面的世界发生了变化,而你无法控制它。文件夹移动,用户权限更改,出现新的磁盘驱动器,旧的磁盘驱动器被删除。你只想在一个地方关心那样的东西。因此,包装 - 我们称之为DirectoryResolver像安迪怀特建议ealier。

因此,包装您的文件系统调用,提取一个接口,并在需要与文件系统进行通信的位置注入该接口。