Home > database >  Path.Combine returns null when Moq is used
Path.Combine returns null when Moq is used

Time:05-02

I use moq 4.17.2 and FileSystem 17.0.3 for my tests.

For some reason, if the line (4) is included I always get null whenever I call fileSystem.Object.Path.Combine (e.g. in line (7)). But, when I remove line 4, then the Path.Combine works as expected. What can be the problem?

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

CodePudding user response:

When you setup fs.Path.GetDirectoryName MOQ will first auto-mock the Path property recursively with a mocked IPath and will thus return null by default when you try to invoke a member that was not explicitly setup.

When you don't mock it the base class (FileSystem) initializes a PathWrapper implementation in its constructor and that is what is being invoked in your example when it behaves as you expected it.

/// <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

Do the same for those properties like you did with FileSystem and setup the members you want to override.

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");
  • Related