Skip to content

Instantly share code, notes, and snippets.

@benvillalobos
Last active May 10, 2024 18:38
Show Gist options
  • Save benvillalobos/a14436f31cdb004942055f87261ac9bf to your computer and use it in GitHub Desktop.
Save benvillalobos/a14436f31cdb004942055f87261ac9bf to your computer and use it in GitHub Desktop.
C# Unit Testing: Verifying ILogger Output with Moq

Context

Using the Moq framework, it's non-trivial in some cases to verify "Did my logger actually log X message?" The first important note is you can't use Moq on extension methods, so you can't directly check LogWarning for example. The workaround is to mock the method that the extension method calls..

For example, I want to verify that LogWarning(mymsg) was logged, but LogWarning is an extension method. So instead of checking that LogWarning was called, we check that Log was called because LogWarning eventually calls Log.

Finally, this SO post showed me how to verify that specific message was logged.

Update: I found Moq.ILogger after implementing this, so you may want to look into that if you're hitting this!

Setup Logic

private Mock<ILogger<FooClass>> _mockLogger = _mockLogger = new Mock<ILogger<FooClass>>();

Checking a specific message was logged

_mockLogger.Verify(
                    logger => logger.Log<It.IsAnyType>( // Must use logger.Log<It.IsAnyType> to sub-out FormattedLogValues, the internal class
                              LogLevel.Warning, // Match whichever log level you want here
                              0, // EventId
                              It.Is<It.IsAnyType>((o, t) => string.Equals("Work item null. Exiting early.", o.ToString())), // The type here must match the `logger.Log<T>` type used above
                              It.IsAny<Exception>(), // Whatever exception may have been logged with it, change as needed.
                              (Func<It.IsAnyType, Exception?, string>) It.IsAny<object>()), // The message formatter
                              Times.Once); // How many times we expect this particular method to be called

Etc. links

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment