测试记录器的输出 - xUnit .NET Core 3.1

Testing the Output of a Logger - xUnit .NET Core 3.1

我正在尝试找出如何测试我的 Serilog 日志库中的消息和日志级别是否正确。

我正在使用 Serilog.Sinks.TextWriter,它将 Serilog 的输出作为 string,当我打印到控制台时,我得到这些行:

[16:44:03 INF] hello // actual log
2020-09-08 16:44:03.117 +01:00 [Information] hello // from StringWriter

我有这个不完整的方法:

[Fact]
public void LogInfo_InfoOutputCorrect()
{
    var logger = new Logger();

    const string message = "Test Info Log Output";
    const string level = "[Information]";

    logger.LogInfo(message); // log info method
    string returnMessage = logger.LogMessages(); // string from StringWriter
}

上面第二行的消息 我想我可以使用 Contains 字符串方法来查看消息和日志级别是否匹配。

returnMessage.Contains(level) && returnMessage.Contains(message)

但不知道该怎么做。

这里有一个用于检查 Serilog 输出的相当快速和肮脏的解决方案。当然,您可以开发这个解决方案,远远超出我在这里介绍的范围,但这应该能让您开始行动。

    // The system under test
    public class MyImportantBehaviour
    {
        public void Run(Serilog.ILogger logger)
        {
            logger.Information("My important log message");
        }
    }

    // The test
    public class MyImportantBehaviourTests
    {
        [Fact]
        public void ExampleTest()
        {
            Queue<LogEvent> logEvents = new Queue<LogEvent>();

            Serilog.ILogger logger = new LoggerConfiguration()
                .MinimumLevel.Verbose()
                .WriteTo.InMemorySink(logEvents)
                .CreateLogger();

            new MyImportantBehaviour().Run(logger);

            logEvents.First().Level.Should().Be(LogEventLevel.Information);
            logEvents.First().MessageTemplate.Should().Be("My important log message");
        }
    }

    public sealed class InMemorySink : ILogEventSink
    {
        public Queue<LogEvent> LogEvents { get; }

        public InMemorySink(Queue<LogEvent> logEvents)
        {
            LogEvents = logEvents;
        }

        public void Emit(LogEvent logEvent)
        {
            LogEvents.Enqueue(logEvent);
        }
    }


    public static class InMemorySinkExtensions
    {
        public static LoggerConfiguration InMemorySink(this LoggerSinkConfiguration loggerConfiguration, Queue<LogEvent> logEvents)
        {
            return loggerConfiguration.Sink(new InMemorySink(logEvents));
        }
    }

如果您使用的是静态记录器(即 Log.Logger),那么它会变得有点棘手。您可以使用以下方法完成类似的事情,但如果在多个线程上进行测试 运行,您可能会 运行 遇到问题。最好在需要此类测试的地方为记录器使用依赖注入。

    Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Verbose()
                .WriteTo.InMemorySink(logLines)
                .CreateLogger();