Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.6k views
in Technique[技术] by (71.8m points)

c# - Implement full logging in Integration Test

I'm creating a new app in .Net Core 3.1.

I have the database created, and now I'm working on the business logic, which is in a collection of services. Before I start to create the API or the UI (ie: any web-app type project), I want to 100% get all of the Data Access and Services working as expected first... including logging. To make sure this is all working together as it should, I want to create some integration tests.

The problem I am running into is I am REALLY struggling with how to get logging working. Every tutorial, document, and all of the examples I can find assume you have a Program.cs and Startup.cs.

NOTE 1: I want the logging to work just as it would in production, which means all the way to SQL. No mocking. No substitution. No replacing.

NOTE 2: I don't care so much about logging from the test. I want logging to work in the service.

Here is an example of an integration test (xUnit) class that I have so far. It's working but has no logging.

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

The DI is working because of NuGet Xunit.DependencyInjection.

And then in the service...

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

The test passes, and the account is properly created in the database. However, as best as I can tell, this line doesn't do anything:

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

I understand why. Microsoft.Extensions.Logging is just an abstraction, and I need to implement some concrete logging (with SeriLog or Log4Net, etc.)

This brings me back to my original question: For the life of me, I can not find a working tutorial on how to get either one of those (SeriLog or Log4Net) working within an integration test (xUnit in particular).

Any help, or point in the right direction, or a link to a tutorial would be wonderful. Thanks.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Add Logging to the service collection using 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>();
    }
}

This will add the factory and open generic for ILogger<> so that they can be injected where needed.

Configure the logging as desired for where that information should go.

There are built-in providers that ASP.NET Core includes as part of the shared framework, but since this is an isolated test you have to add the desired providers as needed.

For example

//...

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.

Reference: Logging in .NET Core and ASP.NET Core


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...