【问题标题】:Mock log file for unit test in .NET Core application.NET Core 应用程序中单元测试的模拟日志文件
【发布时间】:2020-10-06 06:04:00
【问题描述】:

在我的 C# 应用程序中,我有一个 getLogFile,它是通过调用 GetLogFile() 方法设置的:

private static string getLogFile = GetLogFile();

private static string GetLogFile()
{
    var fileTarget = (FileTarget)LogManager.Configuration.FindTargetByName("file-target");
    var logEventInfo = new LogEventInfo();
    string fileName = fileTarget.FileName.Render(logEventInfo);
    if (!File.Exists(fileName))
        throw new Exception("Log file does not exist.");
    return fileName;
}

我现在正在尝试对一些需要设置 getLogFile 变量的代码进行单元测试。我想以某种方式模拟它,因为我想使用特定的日志数据进行测试,但不知道如何去做。我该怎么做?

【问题讨论】:

  • 不要尝试模拟私有字段,而是使用 .NET Core 的日志记录(或任何其他日志记录库,如 Serilog、NLog)并模拟ILogger 接口或添加测试接收器而不是实际接收器
  • 顺便说一句,无论如何你都必须使用ILogger - 所有需要日志记录的 .NET Core 包都希望它存在
  • 这能回答你的问题吗? Is it possible to mock NLog log methods?

标签: c# asp.net unit-testing .net-core nlog


【解决方案1】:

“模拟”private static 字段或方法实际上是不可能的。 将这种方法作为另一个类的私有成员,就像违反单一职责原则一样。

您可能应该将此行为重构为一个单独的类并将其隐藏在接口后面。我不完全确定 NLog 代码的作用,但您的方法似乎真正做的不是提供日志文件,而是提供日志文件的名称(您返回 fileName)所以这就是它的样子:

public interface ILogFileNameProvider 
{
    string GetLogFileName();
}

public class DefaultLogFileNameProvider : ILogFileNameProvider
{
    public string GetLogFileName()
    {
         // your code ommitted
    }
}

这只是一个关于如何处理它的示例。命名/结构以及如何使用它取决于您。 然后可以将该接口注入到当前具有私有方法的 using 类中。可以模拟此依赖项/调用。

与构造函数注入一起使用:

public class LogFileNameUsingService
{
    private readonly ILogFileNameProvider _logFileNameProvider;

    public LogFileNameUsingService(ILogFileNameProvider logFileNameProvider)
    {
        _logFileNameProvider = logFileNameProvider;
    }
}

xUnitAutoMocker 为例进行测试:

[Theory]
public void TestWithMockedLogFileName()
{
    //Arrange
    var mocker = new AutoMocker();
    var logFileNameProviderMock = mocker.GetMock<ILogFileNameProvider>();
    logFileNameProviderMock.Setup(x => x.GetLogFileName()).Returns("your mocked file name.log");
    var sut = mocker.CreateInstance<LogFileNameUsingService>();
    //Act
    var result = sut.TestedMethodWhichUsesLogFileName();
    //Assert whatever you want to test
}

这也允许您换出当前逻辑以在以后获取日志文件,而无需更改现有类的逻辑。

【讨论】:

  • 谢谢@BloodyMettle。什么是AutoMocker()
  • @runnerpaul - AutoMocker 是 Moq 框架的扩展,它简化了模拟设置:AutoMock Github repository。它也可以作为 nuget 包使用:AutoMock Nuget
猜你喜欢
  • 2017-04-14
  • 1970-01-01
  • 2018-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多