如何将TestServer输出记录到测试控制台



我目前正在编写一个集成测试(https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-5.0(,用于我的ASP.Net Core 5 REST API。API使用Serilog进行日志记录(使用静态Serilog Logger(。我正在使用NUnit、Visual Studio 2019和Resharper运行测试。

我希望在API代码运行时记录的所有消息在测试控制台输出中都可见
例如,如果调用此控制器方法:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Serilog;
namespace My.Crazy.Api.Controllers
{    
public sealed class WheelsController : Controller
{
[HttpGet("getwheels")]        
public async Task<IActionResult> Get()
{            
Log.Error("An extremely urgent error");         
return Ok();
}
}
}

我期望";一个极其紧急的错误";要在测试控制台中显示的消息
然而,这并没有发生。

这是我的TestServer设置:

[OneTimeSetUp]
public async Task Setup()
{            
var hostBuilder = new HostBuilder()
.ConfigureWebHost(webHost =>
{
webHost.UseTestServer();
webHost.UseStartup<Startup>();  // Startup is the API project's Startup class

Log.Logger = new LoggerConfiguration().WriteTo.Console().CreateLogger();
});
var host = await hostBuilder.StartAsync();

_client = host.GetTestClient();
}  
[Test]
public async Task FirstTest() 
{
var response = await _client.GetAsync("getwheels");
}

我还尝试过使用自定义接收器进行日志记录:

...
// in the test setup
Log.Logger = new LoggerConfiguration().WriteTo.Sink(new CustomSink()).CreateLogger();
...
public class CustomSink : ILogEventSink
{
public void Emit(LogEvent logEvent)
{
var message = logEvent.RenderMessage();
Console.WriteLine(message);
}
}

这不起作用。然而,我已经确认,当API代码记录任何消息时,将调用Emit方法。

最后,我尝试使用文件输出:

Log.Logger = new LoggerConfiguration().WriteTo.File("C:\temp\test_output.txt").CreateLogger();

正如预期的那样。但是,我仍然想登录控制台。

这可能吗?

不幸的是,对Serilog或NUnit使用任何其他方法都不是一种选择。

所以我会尝试使用带有记录器的自定义记录器提供程序:

记录器提供商:

public class NUnitLoggerProvider : ILoggerProvider
{
public ILogger CreateLogger(string categoryName)
{
return new NUnitLogger();
}
public void Dispose()
{
}
}

记录器:

public class NUnitLogger : ILogger, IDisposable
{
public void Dispose()
{
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
Func<TState, Exception, string> formatter) {
var message = formatter(state, exception);
Debug.WriteLine(message);
}
public bool IsEnabled(LogLevel logLevel) => true;
public IDisposable BeginScope<TState>(TState state) => this;
}    

然后在测试文件中:

var hostBuilder = new HostBuilder()
.ConfigureWebHost(webHost =>
{
webHost.UseTestServer()
.UseStartup<TestStartup>()
.ConfigureLogging((hostBuilderContext, logging) =>
{
logging.Services.AddSingleton<ILoggerProvider, NUnitLoggerProvider>();
});
});            

您可以使用其他东西来登录.,而不是Debug.WriteLine(消息(

我也遇到了同样的问题。经过几天的挖掘,我找到了初始化测试服务器的解决方法。关键在于将默认为falsePreserveExecutionContext设置为true。将其设置为true会将日志带到测试输出。False-没有服务器日志可见,只有客户端日志可见。

var path = Assembly.GetAssembly(typeof(MyTestServer))?.Location;
var directoryName = Path.GetDirectoryName(path);
if (directoryName == null)
throw new InvalidOperationException("Cannot obtain startup directory name");
var hostBuilder = new WebHostBuilder()
.UseContentRoot(directoryName)
.ConfigureAppConfiguration(
configurationBuilder => configurationBuilder.AddJsonFile("appsettings.json", false))
.UseStartup<Startup>()
.ConfigureTestServices(services =>
{
//adding mock services here
});
server = new TestServer(hostBuilder) 
{
//set this to true!!!
PreserveExecutionContext = true 
};

注意:我们正在.NET7上运行这些测试(以及正在测试的系统(。我不确定这是否有什么不同。

最新更新