如何MOQ System.IO.FileInfo类...或没有接口的任何其他类?

时间:2009-10-17 16:28:52

标签: c# .net unit-testing interface moq

我正在为我创建的记录器类编写一些单元测试,我想模拟文件类。我找不到我需要用来创建MOQ的接口......那么如何在没有接口的情况下成功MOQ一个类?

我还不清楚如何在没有可用接口的情况下使用依赖注入:

private FileInfo _logFile;

public LogEventProcessorTextFile(FileInfo logFile) {
    _logFile = logFile;
}

当我真的想做这样的事情时(注意IFileInfo而不是FileInfo):

private IFileInfo _logFile;

public LogEventProcessorTextFile(IFileInfo logFile) {
    _logFile = logFile;
}

4 个答案:

答案 0 :(得分:32)

设计代码,以便不使用直接访问FileInfo类,而是访问具有相同功能的接口(以IFileInfo命名)。在生产代码中,您将使用一个只将其所有功能委托给系统FileInfo类的类,但对于单元测试,您可以模拟该接口。

例如,在我根据当前日期采取不同行动的应用程序中,我声明了以下界面:

interface IDateTimeProvider
{
    DateTime Today();
}

生产课只是:

class DateTimeProvider : IDateTimeProvider
{
    public DateTime Today()
    {
        return DateTime.Today;
    }
}

您可以使用依赖注入引擎来补充此方法,以确定是否应在每种情况下使用真实类或模拟。

答案 1 :(得分:19)

使用SystemWrapper,这是一个为许多.NET类提供接口和可模拟包装类的库,这些类本身不实现接口。

答案 2 :(得分:2)

这可以帮助您轻松创建静态或不可模拟的第三方类的包装类。此工具将在Visual Studio项目上生成Interface和任何现有类(如System.IO)的具体包装类。

https://www.nuget.org/packages/Digitrish.WrapperGenerator/

答案 3 :(得分:0)

将以下 nuget 包添加到您的 csproj:

<ItemGroup>
  <PackageReference Include="System.IO.Abstractions" Version="13.2.29" />
</ItemGroup>

System.IO.Abstractions.FileSystem 注入您的类:

  public class FileLogger
  {
    private readonly IFileSystem fileSystem;

    public FileLogger(System.IO.Abstractions.IFileSystem fileSystem) // new FileSystem()
    {
      this.fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
    }
    
    public void LogEventProcessorTextFile(string filePath)
    {
      IFileInfo fileInfo = fileSystem.FileInfo.FromFileName(filePath);

      LogEventProcessorTextFile(fileInfo);
    }

    private System.IO.Abstractions.IFileInfo _logFile;

    public void LogEventProcessorTextFile(IFileInfo logFile) {
      _logFile = logFile;
    }
  }

起订量示例:

private Mock<IFileSystem> FileSystemMock { get; set; }

[SetUp]
public void Setup()
{
  var file = Mock.Of<IFileInfo>();
  var directoryInfo = Mock.Of<IDirectoryInfo>();

  Mock.Get(file).Setup(c => c.Exists).Returns(true);

  FileSystemMock = new Mock<IFileSystem>();

  FileSystemMock.Setup(c => c.FileInfo.FromFileName(It.IsAny<string>())).Returns(file);
  FileSystemMock.Setup(c => c.DirectoryInfo.FromDirectoryName("Settings")).Returns(directoryInfo);
}