Testing Serilog Logging with MEL and TestCorrelator
Logging as a cross-cutting concern might be implemented in one of plenty of ways. Recently I ran into an attribute-based implementation using passive attributes. What happened was at certain points in the attributed object's lifecycle it had to write messages to a logger. As the author did not want to cramp logging into the production code, they decided to use a passive attribute and a filter checking for said attribute to take care of logging.
However, the filter was not tested, lowering our test coverage.
What I had to do was injecting a mocked Microsoft.ExtensibilityLogging.ILogger<T> into the filter. Easy, right?
Well, sort of. The project uses Serilog for logging. Serilog does support testing through the rather useful TestCorrelator Sink. The canonical way of creating a TestCorrelator is as follows:
Serilog.ILogger logger = new LoggerConfiguration().WriteTo.TestCorrelator().CreateLogger();using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Extensions.Logging;
public class SerilogTypedLogger<T> : Microsoft.Extensions.Logging.ILogger<T>
{
Microsoft.Extensions.Logging.ILogger _logger;
public SerilogTypedLogger(Serilog.ILogger logger)
{
using (var logfactory = new SerilogLoggerFactory(logger))
_logger = logfactory.CreateLogger(typeof(T).FullName);
}
IDisposable Microsoft.Extensions.Logging.ILogger.BeginScope<TState>(TState state) =>
_logger.BeginScope<TState>(state);
bool Microsoft.Extensions.Logging.ILogger.IsEnabled(LogLevel logLevel) =>
_logger.IsEnabled(logLevel);
void Microsoft.Extensions.Logging.ILogger.Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) =>
_logger.Log<TState>(logLevel, eventId, state, exception, formatter);
}
Comments
Post a Comment