ASP.NET Core makes it extremely easy to log information, warnings, errors and the like by injecting the generic
ILogger<T> interface. However, unit-testing becomes a little bit harder, so let us see why and how we can solve this with ease.
In the examples below, we will be using the mocking framework Moq to verify that a certain message is getting logged.
Service under test
Let’s take a closer look to a service responsible for sending template based e-mails.
Writing the obvious test
Now, we want to make sure that an error is being logged in case
_smtpMailer.Send throws an exception.
The first attempt would be to write the test like this:
LogWarning etc are extensions methods, we’re getting the following run-time exception:
Message: System.NotSupportedException : Invalid verify on an extension method.
As it turns out, the
ILogger<> interface is pretty simple, but contains a rather complex
Log method that is harder to setup or verify in your unit-tests.
An elegant solution to this problem is to create a small abstract logger class in our unit-test project:
…and use a mock of that class in our tests. We can now rewrite the test like this:
In this post we have seen one way to keep unit-testing using
ILogger<T> clean and easy. Of course this is not the only way, but from the many solutions I’ve tried I found this one to be the most elegant and practical solution.
If you have another neat way to get around with tests like this, I’d be glad to hear your solution.