如何为无参构造的静态无返回值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
相关产品推荐
相关产品推荐

