.NET Core では、ロギングフレームワークとしてデフォルトの Microsoft.Extensions.Logging
を使用することが多いと思います。
その際、ILogger
に対してログ出力を行います。
その一方で、テスティングフレームワークとして xUnit を使用している場合、テストエクスプローラーにデバッグ用のログを表示するために、ITestOutputHelper
に対してログ出力を行います。
ここで、テスト時の ILogger
の出力先として ITestOutputHelper
を指定できれば、プロダクトコード内のログもテストエクスプローラーに簡単に出力できて便利だなと思い、調べてみたら以下の記事にやり方が載っていたので試してみました。
環境
- .NET Core 2.2
Logger の作成
サンプルコードをそのまま引用しますが・・・。
public class Example
{
private readonly ILogger<Example> _logger;
public Example(ITestOutputHelper testOutputHelper)
{
var loggerFactory = new LoggerFactory();
loggerFactory.AddProvider(new XunitLoggerProvider(testOutputHelper));
_logger = loggerFactory.CreateLogger<Example>();
}
[Fact]
public void Test()
{
_logger.LogDebug("Foo bar baz");
}
}
XunitLoggerProvider
は Microsoft.Extensions.Logging
と xUnit のテスト出力を統合するための処理です。
public class XunitLoggerProvider : ILoggerProvider
{
private readonly ITestOutputHelper _testOutputHelper;
public XunitLoggerProvider(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
}
public ILogger CreateLogger(string categoryName)
=> new XunitLogger(_testOutputHelper, categoryName);
public void Dispose()
{ }
}
public class XunitLogger : ILogger
{
private readonly ITestOutputHelper _testOutputHelper;
private readonly string _categoryName;
public XunitLogger(ITestOutputHelper testOutputHelper, string categoryName)
{
_testOutputHelper = testOutputHelper;
_categoryName = categoryName;
}
public IDisposable BeginScope<TState>(TState state)
=> NoopDisposable.Instance;
public bool IsEnabled(LogLevel logLevel)
=> true;
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
_testOutputHelper.WriteLine($"{_categoryName} [{eventId}] {formatter(state, exception)}");
if (exception != null)
_testOutputHelper.WriteLine(exception.ToString());
}
private class NoopDisposable : IDisposable
{
public static NoopDisposable Instance = new NoopDisposable();
public void Dispose()
{ }
}
}