如何同时模拟Directory.getFiles确保生产代码也能运行。例如,如果运行单元测试,它将运行模拟数据,如果在运行时生产中并且实际上已经传递了参数,则它将调用System.io.Directory。
答案 0 :(得分:1)
我的建议是您使用System.IO.Abstractions,可从NuGet安装。然后,您将代码编码到接口IFileSystem
,而不是直接编码到System.IO File
,Directory
等对象。
因此,无论何时需要访问这些方法,都需要注入IFileSystem
,这意味着必须向依赖注入控制器注册FileSystem
的{{1}}实例,或者您需要将服务实例化为IFileSystem
,那里有一个使用new MyService(new FileSystem())
的构造函数参数。请注意,DI是执行此操作的首选方法。
让我们创建一个简单的服务,该服务返回当前目录中的文件:
IFileSystem
在这里您可以看到我们接受public class MyService
{
private readonly IFileSystem _fileSystem;
public MyService(IFileSystem fileSystem)
{
this._fileSystem = fileSystem;
}
public string[] GetFileNames()
{
return _fileSystem.Directory.GetFiles(_fileSystem.Directory.GetCurrentDirectory());
}
}
,它将被注入我们的班级。我们的IFileSystem
方法只获取当前目录,获取其中的文件,然后返回它们。
现在让我们在生产代码中使用它:
GetFileNames()
嘿,请记住,它会打印出该项目的build文件夹的预期文件列表。
现在,我们如何测试它?为了这个示例,我使用xUnit和Moq。我的单元测试项目中也包含了// FileSystem should be registered with your dependency injection container,
// as should MyService. MyService should be resolved through the container
// and not manually instantiated as here.
var fileSystem = new FileSystem();
var service = new MyService(fileSystem);
var files = service.GetFileNames();
foreach (var file in files)
{
Console.WriteLine(file);
}
NuGet软件包。
首先,我们需要模拟System.IO.Abstractions
对象:
IFileSystem
现在要对其进行测试,我们只需要将其传递到服务中并调用此方法即可:
var mockDirectory = new Mock<IDirectory>();
// set up the GetCurrentDirectory() method to return c:\
mockDirectory.Setup(g => g.GetCurrentDirectory()).Returns(@"c:\");
// Set up the GetFiles method to return c:\test.txt and c:\test2.txt where the path passed is c:\
mockDirectory.Setup(g => g.GetFiles(It.Is<string>(@"c:\"))).Returns(new[] { @"c:\test.txt", @"c:\test2.txt" });
var mockFileSystem = new Mock<IFileSystem>();
// Set up IFileSystem's .Directory property to return the mock of IDirectory that we created above
mockFileSystem.SetupGet(g => g.Directory).Returns(mockDirectory.Object);
// Create an instance of the mock that we can use in our service
var fileSystem = mockFileSystem.Object;
这现在将使用我们在var myService = new MyService(fileSystem);
var files = myService.GetFileNames();
var expected = new[] { @"c:\test.txt", @"c:\test2.txt" };
Assert.True(files.SequenceEqual(expected));
方法中模拟的IFileSystem
的实现,因此我们可以对其进行测试。请注意,如果您使用GetFileNames
的不同重载,则需要模拟相关方法。
答案 1 :(得分:0)
您可以创建自己的包装器类,例如
public interface IFileWrapper
{
FileInfo[] GetFiles(DirectoryInfo di);
}
public class FileWrapper : IFileWrapper
{
public FileInfo[] GetFiles(DirectoryInfo di)
{
return di.GetFiles();
}
}
然后您应该能够模拟出结果。
或者有一些可用的软件包,
希望有帮助