C# 单元测试 void 静态方法

C# UnitTest void static method

我正在尝试对应用程序中的记录器进行单元测试。 例如,我需要测试方法 Logger.info("some message"),但此方法是静态的并且 return 无效。 在 Google 上搜索,我知道我必须使用 Moq,但无法在 UnitTest class 上实现它。 Logger 构造函数没有参数,在 x.Debug 中我有一个错误提示我无法访问 来自实例参考。 有没有办法在不编辑生产代码的情况下实现单元测试?

[TestClass()]
public class LoggerTests
{
    [TestMethod()]
    public void DebugTest()
    { 
        var mock = new Mock<Logger>();
        mock.Setup(x => x.Debug(It.IsAny<string>());
        new Logger(mock.Object).AddLog("testing");
        mock.VerifyAll;
    }
}

Program.cs

private static void ConfigureLogger()
{
    Logger.AddLog(new NLogAppender());
    Logger.Level = TraceLevel.Verbose;
    Logger.Info("Configured Logger");
}

Logger.cs

public class Logger
{
    public static readonly List<IAppender> loggings = new List<IAppender>();

    public static void AddLog(IAppender appender)
    {
        loggings.Add(appender);
    }

    public static TraceLevel Level { get; set; }

    static Logger()
    {
        Level = TraceLevel.Verbose;
    }

    public static void Info(string message)
    {
        LogMessage(message);
    }
}

NlogAppender.cs

public class NLogAppender : IAppender
{
    public NLog.Logger logger;

    public NLogAppender()
    {
        logger = LogManager.GetLogger(nameof(NLogAppender));
    }

    public void AddLog(string str)
    {
    }
}

IAppender.cs

public interface IAppender
{
    void AddLog(string str);
}

您不能模拟静态 class,也不应模拟正在测试的 class/system。

向记录器添加模拟附加程序:

// Arrange
var logString = "test-info"

var appenderMock = new Mock<IAppender>();

appenderMock.Setup(a => a.AddLog(logString));

Logger.AddLog(appenderMock.Object);

// Act
Logger.Info(logString);

// Assert
// TODO: exactly once
appenderMock.VerifyAll();

请注意,此静态 class 可能会在测试之间保留数据,从而导致意外结果,请咨询您的测试框架以进行配置。

除此之外,您通常不想推出自己的日志记录基础设施,有很多事情您可能会做错,为什么要重新发明轮子?大量 ILogger(<T>) 实现。