Sometimes there’s a path in a service or application that you want to test where all it does is log something and return. You could check other things, but sometimes it is hard to check to see if something didn’t happen… and it would be a lot easier to know if something did happen, like a log message. Or, heck, maybe you just really want to make sure that logging happened! Logging is important and can save your skin, so… I get it.
Scenario
Consider this scenario using Common Logging, a popular logging abstraction framework for C#:
Obviously this is contrived, and we could easily check to make sure that _database.AddOrder is not called to verify that we hit the conditional, but suppose that there were more conditionals that you hit, or that you had some kind of consumer on your logging endpoint that would trigger an alert if certain log messages are seen. In that case, you might want to know that you hit this specific branch of the code when provided with a set of parameters.
Problem
The problem is that we have our ILog marked as readonly and being initialized through Common Logging’s LogManager. Presumably NLog or similar is configured in our application’s startup to handle how logs are created, so this works just fine at runtime. If you’re using a dependency injection framework, you could inject the ILog in to the constructor of MyService… but if you’re not, it makes it a little bit tricky to provided a mocked ILog to test and make sure that an expected log message was issued. You could use reflection to set the backing field if you really wanted to, but that would probably involve adding an additional dependency to your project or knowing a lot more about how C# does things under the covers… and, I mean, if that’s your thing, that’s cool, but I’d rather just do it an easy way.
LogManager
Luckily, LogManager is easily told how to create loggers, so we can use that to our advantage and make a fake adapter to provide a mock, which we can then verify at our leisure.
As you can see, it wasn’t exactly straightforward, so I wrote it down. Hopefully its useful!