如何在C# Xunit中模拟静态接口?解决PerformanceLogger空引用异常
问题解决:PerformanceLogger静态TelemetryClient未赋值导致测试报错
问题根源
你的PerformanceLogger类中MyTelemetryClient是静态属性,属于类级别的全局状态。测试代码里虽然创建了Mock<IMyTelemetryClient>实例,但没有将该实例赋值给PerformanceLogger.MyTelemetryClient,导致调用Dispose时触发InvalidOperationException。
另外还有一个细节问题:你在测试中对AddEvent的Setup参数是Dictionary<string, string>类型,但实际Dispose方法里调用的是两个string参数的重载,参数类型不匹配会导致后续验证失败。
解决方案1:修复现有静态属性的测试逻辑
通过给静态属性赋值并做测试隔离,避免影响其他测试用例:
public class PerformanceLoggerTests : IDisposable { private readonly Mock<IMyTelemetryClient> _myClient; public PerformanceLoggerTests() { _myClient = new Mock<IMyTelemetryClient>(); // 初始化静态属性 PerformanceLogger.MyTelemetryClient = _myClient.Object; } [Fact] public void Test_PerformanceLogger() { // 匹配实际调用的参数类型(两个string) _myClient.Setup(x => x.AddEvent(It.IsAny<string>(), It.IsAny<string>())); var service = new PerformanceLogger(); // 执行Dispose service.Dispose(); // 验证方法是否按预期被调用 _myClient.Verify(x => x.AddEvent("N/A", "someTest"), Times.Once); } // 测试结束后重置静态属性,避免污染其他测试 public void Dispose() { PerformanceLogger.MyTelemetryClient = null; } }
解决方案2:重构为构造函数注入(推荐)
静态依赖会导致测试隔离性差、维护成本高,建议将MyTelemetryClient改为实例属性,通过构造函数注入依赖:
修改PerformanceLogger类
public class PerformanceLogger : IDisposable { private readonly IMyTelemetryClient _myTelemetryClient; // 构造函数注入,确保实例创建时依赖已就绪 public PerformanceLogger(IMyTelemetryClient myTelemetryClient) { _myTelemetryClient = myTelemetryClient ?? throw new ArgumentNullException(nameof(myTelemetryClient)); } public void Dispose() { _myTelemetryClient.AddEvent("N/A", "someTest"); } }
对应测试代码
public class PerformanceLoggerTests { private readonly Mock<IMyTelemetryClient> _myClient; public PerformanceLoggerTests() { _myClient = new Mock<IMyTelemetryClient>(); } [Fact] public void Test_PerformanceLogger() { _myClient.Setup(x => x.AddEvent("N/A", "someTest")); // 直接通过构造函数传入Mock实例 var service = new PerformanceLogger(_myClient.Object); service.Dispose(); _myClient.Verify(x => x.AddEvent("N/A", "someTest"), Times.Once); } }
内容的提问来源于stack exchange,提问作者Mukesh
相关产品推荐
相关产品推荐

