如何测试Serilog的DiagnosticContext是否设置了正确的值?
单元测试验证Serilog DiagnosticContext 属性的方案
DiagnosticContext 未提供公开API直接读取内部存储的属性,属性仅会在日志事件输出时被附加到事件上,你可以通过捕获日志事件的方式做断言,具体实现如下:
步骤1:安装依赖包
使用内存Sink捕获日志事件,安装NuGet包:Serilog.Sinks.InMemory
步骤2:编写测试逻辑
using Serilog; using Serilog.Sinks.InMemory; using Xunit; // 可替换为你使用的单元测试框架 public class DiagnosticContextTests { [Fact] public void Verify_DiagnosticContext_Properties_Set_Correctly() { // 1. 配置Serilog,启用DiagnosticContext富集,用内存Sink捕获日志 var inMemorySink = new InMemorySink(); Log.Logger = new LoggerConfiguration() .Enrich.FromDiagnosticContext() // 必须配置,否则属性不会附加到日志 .WriteTo.Sink(inMemorySink) .CreateLogger(); try { // 2. 模拟业务代码中设置DiagnosticContext的逻辑 using (Serilog.Context.DiagnosticContext.PushProperty("OrderId", 12345)) { Serilog.Context.DiagnosticContext.Set("UserName", "ZhangSan"); // 必须输出一条日志,触发属性附加到日志事件 Log.Information("业务操作执行完成"); } // 3. 捕获日志事件,断言属性 var loggedEvent = inMemorySink.LogEvents.Single(); // 断言OrderId属性存在且值正确 Assert.True(loggedEvent.Properties.TryGetValue("OrderId", out var orderIdVal)); Assert.Equal("12345", orderIdVal.ToString().Trim('"')); // 断言UserName属性存在且值正确 Assert.True(loggedEvent.Properties.TryGetValue("UserName", out var userNameVal)); Assert.Equal("ZhangSan", userNameVal.ToString().Trim('"')); } finally { Log.CloseAndFlush(); } } }
备选方案(不推荐,依赖Serilog内部实现)
如果你不想输出测试日志,可以通过反射读取DiagnosticContext的内部存储,该方案可能在Serilog版本更新后失效:
using System.Reflection; using Serilog.Context; // 读取当前DiagnosticContext的内部属性集合 var currentContext = typeof(DiagnosticContext) .GetField("_current", BindingFlags.NonPublic | BindingFlags.Static) ?.GetValue(null); var properties = currentContext?.GetType() .GetField("_properties", BindingFlags.NonPublic | BindingFlags.Instance) ?.GetValue(currentContext) as IEnumerable<KeyValuePair<string, object>>; // 直接断言properties中的值即可

内容的提问来源于stack exchange,提问作者Yifan Ai
相关产品推荐
相关产品推荐

