我正在学习在单元测试中模拟文件系统,并且有一个我想使用模拟进行测试的简单方法:
public class FileStatsUtility
{
private IFileSystem _fileSystem;
public FileStatsUtility(IFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
public FileStatsUtility() : this(fileSystem: new FileSystem()) //use default implementation which calls System.IO
{
}
public long GetFreeSpaceMb(string folder)
{
// returns the free space in Mb of the filesystem this folder is on
string? driveName = Path.GetPathRoot(folder);
if (!string.IsNullOrEmpty(driveName))
{
var drive = _fileSystem.DriveInfo.New(driveName);
return drive.AvailableFreeSpace / (1024 * 1024);
}
else return -1;
}
}
我尝试在单元测试中注入模拟文件系统
[TestMethod]
public void ShouldReturnCorrectFreeSpaceMb ()
{
var testDir = "C:\anystring";
var fsProviderMock = new Mock<IFileSystem>();
var fsu = new FileStatsUtility(fsProviderMock.Object);
//arrange
fsProviderMock
.Setup(m => m.DriveInfo.New(testDir))
.Returns(new DriveInfo("C:\")
{
DriveType = DriveType.Fixed,
AvailableFreeSpace = 500 * 1024 * 1024
});
//act
var reportedFreeSpace = fsu.GetFreeSpaceMb(testDir);
//assert
}
这不会编译。 DriveType 和AvailableFreeSpace 是只读的。我想我错过了一些简单的东西,但无法理解它。
如何设置模拟以返回填充的 DriveInfo?
对于像文件系统这样复杂的东西,我建议为您的模拟创建一个常规类,而不是使用模拟框架。如果您需要模拟界面的一小部分,模拟框架会很方便。但对于像文件系统这样复杂的东西来说,可能比创建自己的类来模拟内存中的文件系统更好。这也将更容易重用于其他类型的测试。
我还会考虑您打算如何使用文件系统。如果您只想存储和检索数据,您可能会考虑一些更抽象的东西,例如
IFileRepository
,它不关心可用空间或权限等文件系统详细信息。这应该可以更轻松地进行多种实现,并使界面更有用。
如果您只是在 Windows 文件系统周围创建一个薄包装器,那么由于难以复制的所有各种特殊行为,您无法切实地进行任何其他有效的实现。包括测试的模拟实现。例如,考虑一下,