测试记录器的输出 - 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();
我正在尝试找出如何测试我的 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();