Path.Combine returns 使用 Moq 时为空

Path.Combine returns null when Moq is used

我使用 moq 4.17.2 and FileSystem 17.0.3 进行测试。

出于某种原因,如果包含第 (4) 行,我每次调用 fileSystem.Object.Path.Combine 时总是会得到 null(例如在第 (7) 行中)。但是,当我删除第 4 行时,Path.Combine 会按预期工作。可能是什么问题?

1.  var fileSystem = new Mock<FileSystem> { CallBase = true }.As<IFileSystem>();
2.  dirInfo.ExistingFiles.ForEach(existingFile =>
3.  {
4.       fileSystem.Setup(fs => fs.Path.GetDirectoryName(existingFile)).Returns("");
5.       fileSystem.Setup(fs => fs.File.Exists(existingFile)).Returns(true);
6.  });
7. var path = fileSystem.Object.Path.Combine("a", "b");

df

当您设置 fs.Path.GetDirectoryName MOQ 将首先 auto-mock Path 属性 与模拟 IPath 递归,因此 return null 默认情况下,当您尝试调用未明确设置的成员时。

当你不模拟它时,基础 class (FileSystem) 会在其构造函数中初始化一个 PathWrapper 实现,这就是你的示例在其行为时调用的内容正如你所料。

/// <inheritdoc />
public FileSystem()
{
    DriveInfo = new DriveInfoFactory(this);
    DirectoryInfo = new DirectoryInfoFactory(this);
    FileInfo = new FileInfoFactory(this);
    Path = new PathWrapper(this);
    File = new FileWrapper(this);
    Directory = new DirectoryWrapper(this);
    FileStream = new FileStreamFactory();
    FileSystemWatcher = new FileSystemWatcherFactory();
}

Source

In this case, how can I mock GetDirectoryName but make the rest methods of Path work with default implementation

对这些属性执行与 FileSystem 相同的操作,并设置要覆盖的成员。

var fileSystem = new Mock<FileSystem> { CallBase = true }.As<IFileSystem>();

var pathWrapper = new Mock<PathWrapper>(fileSystem.Object);
pathWrapper.CallBase = true;

dirInfo.ExistingFiles.ForEach(existingFile => {
    pathWrapper.Setup(p => p.GetDirectoryName(existingFile)).Returns("");
    fileSystem.Setup(fs => fs.File.Exists(existingFile)).Returns(true);
});

fileSystem.Setup(fs => fs.Path).Returns(pathWrapper.Object);

var path = fileSystem.Object.Path.Combine("a", "b");