简体   繁体   English

如何将TestServer output登录到测试控制台

[英]How to log TestServer output to the test console

I'm currently writing an integration test ( https://learn.microsoft.com/en-us/as.net/core/test/integration-tests?view=as.netcore-5.0 ) for my ASP.Net Core 5 REST API. The API is using Serilog for logging (with the static Serilog Logger).我目前正在为我的 ASP.Net Core 5 编写集成测试( https://learn.microsoft.com/en-us/as.net/core/test/integration-tests?view=as.netcore-5.0 ) REST API。API 使用 Serilog 进行日志记录(使用 static Serilog Logger)。 I am running tests with NUnit, Visual Studio 2019, Resharper.我正在使用 NUnit、Visual Studio 2019、Resharper 运行测试。

I want all the messages, that are logged during the runtime of the API code, to be visible in the test console output.我希望在 API 代码运行期间记录的所有消息在测试控制台 output 中可见。
For example, if this controller method is called:例如,如果调用此 controller 方法:

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

I expect the "An extremely urgent error" message to be shown in the test console.我希望在测试控制台中显示“一个非常紧急的错误”消息。
However, this is not happening.然而,这并没有发生。

Here is my TestServer setup:这是我的测试服务器设置:

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

I have also tried logging with a custom Sink:我还尝试使用自定义接收器进行日志记录:

...
// 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);
    }
}

This does not work as well.这也行不通。 However, I have confirmed that the Emit method is being invoked when API code logs any message.但是,我已确认当 API 代码记录任何消息时,正在调用 Emit 方法。

Finally, I have tried using a File output:最后,我尝试使用文件 output:

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

which worked as expected.按预期工作。 However, I still want to log in the console.但是,我仍然想登录控制台。

Is this possible?这可能吗?

Using anything else for Serilog or NUnit is unfortunately not an option.不幸的是,对 Serilog 或 NUnit 使用其他任何东西都不是一种选择。

So I would try with a custom logger provider with logger:所以我会尝试使用带有记录器的自定义记录器提供程序:

LoggerProvider:记录器提供者:

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

    public void Dispose()
    {
    }
}

Logger:记录器:

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

Then in the test file:然后在测试文件中:

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

And instead of Debug.WriteLine(message) you can use something else to log to.而不是 Debug.WriteLine(message) 您可以使用其他东西来登录。

I had the same problem.我有同样的问题。 After days of digging, I found a workaround with the initialization of the test server.经过几天的挖掘,我找到了测试服务器初始化的解决方法。 The key is in setting to true the PreserveExecutionContext which is by default false .关键在于将PreserveExecutionContext设置为true ,默认情况下为false Setting it to true brings the logs to the test output. False - no server logs are visible, only client ones.将其设置为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 
    };

Note: we're running these tests (and the system under test) on .NET7.注意:我们正在 .NET7 上运行这些测试(以及被测系统)。 I am not sure whether this makes any difference.我不确定这是否有任何区别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM