c# – .net core 2.0 ConfigureLogging xunit test

在我的.NET Core 2.0项目中的xUnit集成测试中,我无法在终端中看到同时打印测试结果的日志消息.在WebHost环境中运行代码时,日志将打印到控制台.

这是我在测试构造函数中配置日志记录的方法

var config = new ConfigurationBuilder()
    .AddJsonFile("appsettings.Tests.json")
    .Build();

var services = new ServiceCollection();

services.AddLogging(options => {
    options.AddConfiguration(config.GetSection("Logging"));
    options.AddConsole();
    options.AddDebug();
});

var serviceProvider = services.BuildServiceProvider();
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger("Test");
logger.LogError("From ctor");

但我没有看到任何日志消息.

解决方法

xUnit在版本2中已更改为不再捕获测试的标准输出

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.

相反,您现在应该使用an explicit mechanism来写入测试输出.基本上,您不是写入控制台,而是写入特殊的ITestOutputHelper.

当然,ASP.NET Core日志记录默认不支持输出机制.幸运的是,为测试输出编写日志记录提供程序并不困难.我刚刚实现了一个快速提供程序,并在下面的答案中包含它.你可以像这样使用它:

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

请注意,通常应避免在单元测试中创建完整的依赖项注入容器.在单元测试中使用DI通常表明您的单元测试不是单元测试,而是集成测试.在单元测试中,您应该只测试一个特定单元并明确地传递其所有依赖项 – 而不仅仅是作为模拟.正如您在上面的示例中所看到的,创建记录器实际上是一个非常简单的事情,没有DI.

正如所承诺的,这是运行上面显示代码所需的XunitLoggerProvider和XunitLogger,以及将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()
        { }
    }
}

相关文章

AntDeploy这个东西非常好用,可以直接将.NET CORE的程序直接发布到docker,刚好我有这个需求,但是程序...
前言 以前需要提供Web服务接口的时候,除了标准的WEBAPI形式,还考虑了OData、GraphQL等形式,虽然实现...
最近想要在程序中嵌入一个C#脚本引擎,在.NET Framework时代用过一个叫做CS-Script的东西,感觉还是不错...
经常使用swagger,可以通过设置[ProducesResponseType]标记接口的返回信息;swagger也能通过接口的参数...
本文属于OData系列 目录 武装你的WEBAPI-OData入门 武装你的WEBAPI-OData便捷查询 武装你的WEBAPI-ODat...
我有一个想法,有一个能够进行跨平台的高性能数据协议规范,能够让数据在两个不同的程序之间进行读取,...