1

我正在尝试为类似于此的代码创建单元测试:

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

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

谢谢。

4

4 回答 4

2

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

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

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

于 2011-04-18T20:57:01.477 回答
1

您将注入一个包装类。

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

然后注入:

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

然后,您可以在注入点模拟该人(此示例使用 Moq 和构造函数注入):

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
于 2011-04-18T20:56:30.623 回答
0

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

因此,包装您的文件系统调用,提取一个接口,并将该接口注入您需要与文件系统通信的地方。

于 2011-04-19T07:01:57.520 回答
0

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

于 2011-04-21T09:01:28.277 回答