.net core 2.0 ConfigureLogging xunit test

柔情痞子 提交于 2019-12-03 03:03:49

xUnit has changed in version 2 to no longer capture the standard output for tests:

If you used xUnit.net 1.x, you may have previously been writing output to Console, Debug, or Trace. When xUnit.net v2 shipped with parallelization turned on by default, this output capture mechanism was no longer appropriate; it is impossible to know which of the many tests that could be running in parallel were responsible for writing to those shared resources.

Instead, you are now supposed to use an explicit mechanism to write to the test output. Basically, instead of writing to the console, you are writing to a special ITestOutputHelper.

Of course, this output mechanism is not supported by default with ASP.NET Core logging. Fortunately, writing a logging provider for the test output isn’t too difficult. I’ve just implemented a quick provider and included it in my answer below. You can use it like this:

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");
    }
}

Note that you usually should avoid creating a complete dependency injection container in unit tests. Having DI in unit tests is usually a sign that your unit test is not a unit test but instead an integration test. In a unit test, you should only test one particular unit and pass all its dependencies explicitly—more than often just as a mock. As you can see in the example above, creating a logger is actually a very simple thing to do without DI.


As promised, this is the XunitLoggerProvider and the XunitLogger which you need to run the code shown above, and to integrate the Microsoft.Extensions.Logging framework with xUnit test output:

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()
        { }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!