How to test the logs from ILogger in .NET

 
 
  • Gérald Barré

You sometimes need to validate that a log message is written to the log. In this post, I describe how to unit test ILogger in .NET Core.

There are multiple strategies:

  • You can use a mock framework like Moq to mock the ILogger interface and validate the right calls are made.
  • You can store all logs in-memory and assert the collection.
  • You can use a file logger and assert the log file.
  • Etc.

In this post, I will use the second strategy. The idea is to use a custom ILogger implementation that stores all logs in-memory and keeps all details (state and scopes). I prefer this method as it is easier to debug a test. Indeed, you can see all logs using the debugger or using the ToString method. Also, the test setup and the assertions are easy to write.

You can use the Meziantou.Extensions.Logging.InMemory NuGet package to get an in-memory logger provider. You can install it using the following command:

Shell
dotnet add package Meziantou.Extensions.Logging.InMemory

Then, you can use the package as follow in your unit test:

C#
// Create the logger
using var loggerProvider = new InMemoryLoggerProvider();
var logger = loggerProvider.CreateLogger("MyLogger");

// Call the method to test
MethodToTest(logger);

// Validate the logs
Assert.Empty(loggerProvider.Logs.Errors);
Assert.Single(loggerProvider.Logs, log => log.Message.Contains("test") && log.EventId.Id == 1);

If you are testing an ASP.NET Core application, you can use the WebApplicationFactory to create a test server and use the InMemoryLoggerProvider as follow:

Shell
dotnet add package Microsoft.AspNetCore.Mvc.Testing
C#
// Create the in-memory logger provider
using var loggerProvider = new InMemoryLoggerProvider();

// Register the provider when creating the WebApplicationFactory
using var factory = new WebApplicationFactory<Program>()
    .WithWebHostBuilder(builder =>
    {
        builder.ConfigureLogging(builder =>
        {
            builder.Services.AddSingleton<ILoggerProvider>(loggerProvider);
        });
    });

// Call the API
using var client = factory.CreateClient();
var str = await client.GetStringAsync("/me");

// Validate the logs
var warning = Assert.Single(loggerProvider.Logs.Warnings);
Assert.Equal("Demo sample", warning.Message);

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee💖 Sponsor on GitHub