You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为无参构造的静态无返回值Logger类编写无需修改生产代码的单元测试

问题分析

你之前的测试代码存在两个核心错误:

  • Logger的所有公开方法都是静态成员,静态成员属于类而非实例,既无法通过实例对象调用,也无法通过Moq直接Mock静态非虚成员
  • Logger没有支持传入Mock对象的公共实例构造函数,你手动写的new Logger(mock.Object)不符合现有类的设计逻辑
解决方案(无需修改生产代码)

利用现有Logger已经实现的Appender扩展机制即可完成测试,不需要对Logger本身做Mock:
Logger内部维护了公开的IAppender集合,你只需要注入一个Mock的IAppender,调用Logger.Info后验证这个Mock实例的AddLog方法是否符合预期调用即可。

完整测试代码

[TestClass()]
public class LoggerTests
{
    // 每次测试结束后清理环境,避免静态变量污染其他测试
    [TestCleanup]
    public void TestCleanup()
    {
        Logger.loggings.Clear();
        Logger.Level = TraceLevel.Verbose;
    }

    [TestMethod()]
    public void Info_ShouldInvokeAppenderAddLog_WhenLogLevelMatches()
    {
        // 构造Mock的IAppender
        var mockAppender = new Mock<IAppender>();
        const string testMessage = "测试日志内容";
        
        // 把Mock实例注册到Logger
        Logger.AddLog(mockAppender.Object);
        
        // 调用待测试的静态Info方法
        Logger.Info(testMessage);
        
        // 验证AddLog方法被正确调用1次,且传入参数匹配
        mockAppender.Verify(p => p.AddLog(testMessage), Times.Once);
    }

    // 可扩展边界测试:日志级别不匹配时不输出
    [TestMethod()]
    public void Info_ShouldNotInvokeAppender_WhenLogLevelIsLowerThanInfo()
    {
        var mockAppender = new Mock<IAppender>();
        Logger.Level = TraceLevel.Warning;
        Logger.AddLog(mockAppender.Object);
        
        Logger.Info("测试日志内容");
        
        mockAppender.Verify(p => p.AddLog(It.IsAny<string>()), Times.Never);
    }
}

注意事项

  • 静态变量是应用域全局共享的,每次测试结束必须清空Logger.loggings集合、恢复日志级别默认值,避免不同测试之间互相干扰
  • 该方案完全基于现有生产代码的设计实现,不需要修改任何生产侧代码

内容的提问来源于stack exchange,提问作者MarcoAgu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 06:36:07