单元测试serilog配置

Veg*_*gar 5 .net serilog .net-core

我有一段代码用于根据一些自定义配置与托管环境相结合来设置 serilog。例如,应用程序在开发中写入一个接收器,在生产中写入另一个接收器。

我想弄清楚如何为这段代码编写测试。基本上,我想编写一个测试,检查仅当环境名称设置为给定值时才添加接收器,并且接收器配置(如日志文件路径)尊重我提供的自定义配置。

但是我没有任何运气找到任何LoggingConfiguration...中获取价值的方法。

有谁知道这是否可能?

Cai*_*ete 5

不幸的是,Serilog 没有公开已配置的接收器列表,因此您目前唯一的选择是使用反射。

如果您查看 Serilog 的源代码,您会看到它将所有配置的接收器分组到一个内部类的实例中,该类SafeAggregateSink负责将日志发送到不同的接收器设置,并在私有字段中保存一个包含所有配置接收器的数组称为_sinks

这是一个简单的例子:

var log = new LoggerConfiguration()
    .WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Verbose)
    .WriteTo.File(path: "log.txt", restrictedToMinimumLevel: LogEventLevel.Verbose)
    .CreateLogger();

var aggregateSinkFieldInfo = log.GetType()
    .GetField("_sink", BindingFlags.Instance | BindingFlags.NonPublic);

var aggregateSink = (ILogEventSink)aggregateSinkFieldInfo?.GetValue(log);

var sinkEnumerableFieldInfo = aggregateSink?.GetType()
    .GetField("_sinks", BindingFlags.Instance | BindingFlags.NonPublic);

var sinks = (ILogEventSink[])sinkEnumerableFieldInfo?
    .GetValue(aggregateSink);

if (sinks != null)
{
    foreach (var sink in sinks)
    {
        Console.WriteLine(sink.GetType().FullName);
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该输出:

Serilog.Sinks.SystemConsole.ConsoleSink
Serilog.Sinks.File.FileSink
Run Code Online (Sandbox Code Playgroud)

注意:请记住,在某些情况下,Serilog 会包装接收器,因此您可能需要先处理这个问题,然后才能找到所需的接收器。例如,如果您限制接收器的最低级别,您的接收器将被包裹到一个 中RestrictedSink,因此您必须掌握它的_sink字段才能获得您正在寻找的“真实”接收器。