在集成测试中实现完整日志记录

Implement full logging in Integration Test

我正在 .Net Core 3.1 中创建一个新应用程序。

我已经创建了数据库,现在我正在研究服务集合中的业务逻辑。在我开始创建 API 或 UI(即:任何 web 应用程序类型的项目)之前,我想 100% 首先让所有数据访问和服务按预期工作......包括记录。为确保一切正常,我想创建一些集成测试。

我 运行 遇到的问题是我真的在为如何使日志记录工作而苦苦挣扎。我能找到的每个教程、文档和所有示例都假设您有 Program.csStartup.cs.

注意 1: 我希望日志记录像在生产中一样工作,这意味着一直到 SQL。没有嘲笑。没有替代品。没有替换。

注意 2: 我不太关心测试日志。我希望日志记录在服务中工作

这是我目前拥有的集成测试 (xUnit) class 的示例。它正在运行,但没有日志记录。

namespace MyApp.Test
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient<IAccountService, AccountService>();
            services.AddTransient<IAppSettings, AppSettings>();
        }
    }

    public class AccountServiceTests
    {
        private readonly IAccountService _account;
        private readonly IAppSettings _settings;

        public AccountServiceTests(IAccountService account, IAppSettings settings)
        {
            _account = account;
            _settings = settings;
        }

        [Fact]
        public async Task AccountService_CreateAccount()
        {
            Account account = new Account( {...} );
            bool result = _account.CreateAccount(account);
            Assert.True(result);
        }
    }
}

由于 NuGet Xunit.DependencyInjection.

,DI 正在运行

然后在服务中...

public class AccountService : ServiceBase, IAccountService
{
        protected readonly ILogger _logger;
        protected readonly IAppSettings _settings;

        public AccountService(ILogger<AccountService> logger, IAppSettings settings) 
        {
            _logger = logger;
            _settings = settings;
        }

        public bool CreateAccount()
        {
            // do stuff
            _logger.Log(LogLevel.Information, "An account was created."); // I WANT THIS TO END UP IN SQL, EVEN FROM THE TEST.
        }
}

测试通过,账户在数据库中正确创建。然而,据我所知,这一行没有做任何事情:

_logger.Log(LogLevel.Information, "An account was created.");

我明白为什么。 Microsoft.Extensions.Logging 只是一个抽象,我需要实现一些具体的日志记录(使用 SeriLog 或 Log4Net 等)

这让我回到了我原来的问题:在我的生活中,我找不到关于如何让其中一个(SeriLog 或 Log4Net)在集成测试(特别是 xUnit)中工作的工作教程.

任何帮助,或指出正确的方向,或 link 教程都将是极好的。谢谢。

配置记录器工厂

using var loggerFactory = LoggerFactory.Create(builder =>
{
    builder
        .AddFilter("Microsoft", LogLevel.Warning)
        .AddFilter("System", LogLevel.Warning)
        .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
        .AddConsole()
        .AddEventLog();
});

然后将其注册为服务

services.AddSingleton(loggerFactory);

如果您只是想查看日志记录在 xUnit 中工作,请将类似以下代码的内容添加到 xUnit 测试的构造函数中,并将其传递给基础构造函数如下。 (我在这里假设您正在使用 WebApplicationFactory 来启动测试中的服务。)

protected readonly WebApplicationFactory<Startup> Factory;

public AccountServiceTests(IAccountService account, IAppSettings settings, ITestOutputHelper testOutputHelper) : base( testOutputHelper )
{
    _account = account;
    _settings = settings;

    Factory = new WebApplicationFactory<Startup>().WithWebHostBuilder(builder =>
        {
            builder.ConfigureTestServices(services =>
            {
                services.AddLogging(logBuilder => logBuilder.AddXUnit(testOutputHelper));
            });
        });
}

这将使您的日志消息显示在测试输出中。

请注意,此处的详细信息可能会因您所拥有的而有所不同,但这是基本思想:xUnit 传入 testOutputHelper 并使用它来初始化测试的日志系统。

以编程方式验证您的测试是否写入了正确的日志消息是另一回事。我没有现成的答案。

使用 LoggingServiceCollectionExtensions.AddLogging

将日志记录添加到服务集合
public class Startup {
    public void ConfigureServices(IServiceCollection services) {
        services.AddLogging(builder => 
            builder.ClearProviders()
                .Add{ProverNameHere}()

            // ... other logging configuration
        );
        services.AddTransient<IAccountService, AccountService>();
        services.AddTransient<IAppSettings, AppSettings>();
    }
}

这将为 ILogger<> 添加工厂和开放泛型,以便可以在需要的地方注入它们。

根据需要为信息的去向配置日志记录。

ASP.NET 核心包含 built-in providers 作为共享框架的一部分,但由于这是一个独立测试,您必须根据需要添加所需的提供程序。

例如

//...

services.AddLogging(builder => builder.AddConsole().AddDebug());

//...

Console

The Console provider logs output to the console.

Debug

The Debug provider writes log output by using the System.Diagnostics.Debug class. Calls to System.Diagnostics.Debug.WriteLine write to the Debug provider.

Logging output from dotnet run and Visual Studio

Logs created with the default logging providers are displayed:

  • In Visual Studio
    • In the Debug output window when debugging.
    • In the ASP.NET Core Web Server window.
  • In the console window when the app is run with dotnet run.

Logs that begin with "Microsoft" categories are from ASP.NET Core framework code. ASP.NET Core and application code use the same logging API and providers.

参考:Logging in .NET Core and ASP.NET Core