单元测试serilog配置

时间:2018-09-28 11:44:55

标签: .net .net-core serilog

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

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

但是我没有运气找到任何从LoggingConfiguration ...

中获取值的方法。

有人知道这是否可能吗?

1 个答案:

答案 0 :(得分:3)

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

如果您戳Serilog's source code,您会看到it groups all configured sinks进入内部类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);
    }
}

这应该输出:

Serilog.Sinks.SystemConsole.ConsoleSink
Serilog.Sinks.File.FileSink

N.B .:请记住,在某些情况下,Serilog会包装接收器,因此在找到所需的接收器之前,您可能需要处理该接收器。例如,如果您限制接收器的最低级别,则接收器将被包裹在RestrictedSink中,因此必须保留其_sink字段才能获得“真实”接收器您正在寻找。