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");
但我没有看到任何日志消息.
解决方法
If you used xUnit.net 1.x,you may have prevIoUsly been writing output to
Console
,Debug
,orTrace
. 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() { } } }