如何将日志从 TestServerFixture 重定向到 .net Core 中的 ITestOutputHelper?

How to get redirect Log from TestServerFixture to ITestOutputHelper in .net Core?

我目前在 VSTS 的构建机器中测试失败,真的很难知道发生了什么。我有很多由 API 生成的日志,这可能真的很有帮助。

我的目的是将我 API 中生成的所有日志重定向到 OutputTestHelper。

使用 Xunit,我有一个 TestServerFixture:

 public class TestServerFixture : IDisposable
    {
        public TestServer Server { get; }
        public HttpClient Client { get; }
        public T GetService<T>() => (T)Server.Host.Services.GetService(typeof(T));

        public TestServerFixture()
        {
            var builder = new WebHostBuilder()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseEnvironment("Development")
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                          .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true)
                          .AddEnvironmentVariables();
                })
                .UseStartup<TestStartup>()
                .ConfigureLogging((hostingContext, logging) =>
                {

                    logging.AddXunit(output); //How Can I get ITestOuputHelper?
                });

            Server = new TestServer(builder);
            Client = Server.CreateClient();
        }
        public void Dispose()
        {
            Server.Dispose();
            Client.Dispose();
        }
    }

正在阅读:

我有一个扩展允许我将 Xunit ITestOutputHelper 添加到需要 ITestOutputHelper 作为参数的记录器 (AddXunit())。

问题是,我找不到在 TestServerFixture 中获取它的方法。我试过了:

您知道配置 TestServerFixture 以将所有日志重定向到 OutpuTestHelper 的方法吗?

如果您的 DI(包括 ILoggerFactory)已经在您的装置上配置了一个写入 xUnit 输出的记录器提供程序实现,那么您应该能够从服务中请求 ILogger<whatever> provider 在你的灯具上(使用你在那里展示给我们的 GetService<T> 方法)。

Microsoft 的记录器 DI 集成注册服务 ILogger<> 以提供来自 LoggerFactory 的记录器(您需要为此注册一个提供者,这就是您使用 AddXunit 扩展所做的事情你的 ConfigureLogging 电话)

我终于找到了解决办法。由于无法从注入访问 ITestOutpuHelper,我没有其他方法可以为每个测试创建一个新的 TestServerFixture class.

我之前有:

public class Users_Tests
{
    [...]
    public Users_Tests(
        TestServerFixture server
        ITestOutputHelper output
    )
    {
        [...]
    }
}

我现在拥有的:

public class Users_Tests
{
    [...]
    public Users_Tests(
        ITestOutputHelper output
    )
    {
        TestServerFixture = new TestServerFixture(output);    
        [...]
    }
}

所以我的 TestServiceFixture 现在是:

public class TestServerFixture : IDisposable
{
    public TestServer Server { get; }
    public HttpClient Client { get; }
    public T GetService<T>() => (T)Server.Host.Services.GetService(typeof(T));

    public TestServerFixture(ITestOutputHelper output)
    {
        var builder = new WebHostBuilder()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseEnvironment("Development")
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                      .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true)
                      .AddEnvironmentVariables();
            })
            .UseStartup<TestStartup>()
            .ConfigureLogging((hostingContext, logging) =>
            {
                logging.AddXunit(output);
            });

        Server = new TestServer(builder);
        Client = Server.CreateClient();
    }
    public void Dispose()
    {
        Server.Dispose();
        Client.Dispose();
    }
}

所以现在所有日志都重定向到输出,这帮助我了解了错误的来源!

如果您没有通过 ITestOutputHelper 获取日志的严格要求,您可以尝试使用 xUnit 中的 IMessageSink 抽象,用于在 TestFixtures 中进行日志记录。

public class SutTests : IClassFixture<TestServerFixture>
{
    private readonly ITestOutputHelper _output; // for logging inside test classes
    private readonly TestServerFixture  _fixture;

    public SutTests(TestServerFixture fixture, ITestOutputHelper output) {
        _fixture = fixture
        _output = output;
    }
    ...
}

public class TestServerFixture : IAsyncLifetime
{
    private readonly IMessageSink _sink; // for logging inside TestFixtures
    public TestServerFixture(IMessageSink sink) {
        _sink = sink;
        _sink.OnMessage(new DiagnosticMessage("Test Server Fixture Created."));
    }

    public async Task InitializeAsync() {
        // initialize stuffs..
        _sink.OnMessage(new DiagnosticMessage("Fixture initialized."));
    }
    ...
}

备注: