.net core 2.0 ConfigureLogging xunit测试 [英] .net core 2.0 ConfigureLogging xunit test
问题描述
在我的.NET Core 2.0项目中的xUnit集成测试中,我看不到终端中的日志消息,该消息也打印了测试结果.在WebHost环境中运行代码时,日志将打印到控制台.
In my xUnit integration test in my .NET Core 2.0 project I cannot see log messages in the terminal that also prints the test results. When the code is run in WebHost environment, the logs are printed out to the console.
这是我在测试的构造函数中配置日志记录的方式:
This is how I configure logging in the test's constructor:
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");
但是我没有看到任何日志消息.
But I don't see any log message.
推荐答案
xUnit在版本2中已更改,不再捕获测试的标准输出:
xUnit has changed in version 2 to no longer capture the standard output for tests:
如果使用的是xUnit.net 1.x,则可能以前已将输出写入
Console
,Debug
或Trace
.默认情况下,当xUnit.net v2附带并行化处于打开状态时,此输出捕获机制不再适用.不可能知道可以并行运行的许多测试中的哪一个负责写入那些共享资源.
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.
相反,您现在应该使用显式机制来写入测试输出.基本上,不是写到控制台,而是写到特殊的ITestOutputHelper
.
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
.
当然,默认情况下,ASP.NET Core日志记录不支持此输出机制.幸运的是,为测试输出编写日志记录提供程序并不是很困难.我刚刚实施了一个快速提供程序,并将其包含在下面的答案中.您可以像这样使用它:
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");
}
}
请注意,通常应避免在单元测试中创建完整的依赖项注入容器.在单元测试中使用DI通常是一个信号,表明您的单元测试不是 unit 测试,而是集成测试.在单元测试中,您应该只测试一个特定的单元并显式地传递其所有依赖关系,而不仅仅是作为一个模拟.如您在上面的示例中所见,创建记录器实际上是没有DI的非常简单的事情.
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.
如所承诺的,这是XunitLoggerProvider
和XunitLogger
,您需要它们运行上面显示的代码,并将Microsoft.Extensions.Logging
框架与xUnit测试输出集成:
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()
{ }
}
}
这篇关于.net core 2.0 ConfigureLogging xunit测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!