
Log4Net is an industry standard for logging. Almost every developer uses it in some point in his/hers professional life. I am no exception, and I needed to write a LogManager wrapper and unit test it.
The purpose of the unit test is to check if the logger logs a message or not, depending on the level of the threshold configured. It should also write exception messages when given. The idea is to use Log4Net MemoryAppender and test the output.
Here is the code (I am using Shouldy for assertion), use it at will:
public interface ILogManager { void Debug(string message, Exception ex = null); void Info(string message, Exception ex = null); void Warn(string message, Exception ex = null); void Error(string message, Exception ex = null); void Fatal(string message, Exception ex = null); } public class LogManager : ILogManager { private readonly ILog _logger; private bool _isDebugEnabled; private bool _isInfoEnabled; private bool _isWarnEnabled; private bool _isErrorEnabled; private bool _isFatalEnabled; public LogManager() { _logger = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); XmlConfigurator.Configure(); SetLoggingLevelConstants(); } public LogManager(ILog logger) { _logger = logger; SetLoggingLevelConstants(); } public void Debug(string message, Exception ex = null) { Log(_isDebugEnabled, _logger.Debug, message, ex); } public void Info(string message, Exception ex = null) { Log(_isInfoEnabled, _logger.Info, message, ex); } public void Warn(string message, Exception ex = null) { Log(_isWarnEnabled, _logger.Warn, message, ex); } public void Error(string message, Exception ex = null) { Log(_isErrorEnabled, _logger.Error, message, ex); } public void Fatal(string message, Exception ex = null) { Log(_isFatalEnabled, _logger.Fatal, message, ex); } private void SetLoggingLevelConstants() { _isDebugEnabled = _logger.IsDebugEnabled; _isInfoEnabled = _logger.IsInfoEnabled; _isWarnEnabled = _logger.IsWarnEnabled; _isErrorEnabled = _logger.IsErrorEnabled; _isFatalEnabled = _logger.IsFatalEnabled; } private static void Log(bool enabled, Action<string, Exception> logAction, string message, Exception exception = null) { if (!enabled) return; logAction(message, exception); } } [TestClass] public class LogManagerShould { private MemoryAppender _appender; private const string LOG_MESSAGE = "test message"; private readonly Exception _exception = new Exception("test exception"); [TestMethod] public void LogDebugMessagesWhenDebugEnabled() { //arrange var logManager = GetLogManager(Level.Debug); //act logManager.Debug(LOG_MESSAGE); //assert GetLogMessage().ShouldBe(LOG_MESSAGE); } [TestMethod] public void LogDebugMessagesWithExceptionWhenDebugEnabled() { //arrange var logManager = GetLogManager(Level.Debug); //act logManager.Debug(LOG_MESSAGE, _exception); //assert GetLogMessage().ShouldBe(LOG_MESSAGE); GetLogException().ShouldBe(GetLogExceptionMessage()); } [TestMethod] public void NotLogDebugMessagesWhenDebugDisabled() { //arrange var logManager = GetLogManager(Level.Info); //act logManager.Debug(LOG_MESSAGE); //assert GetLogMessage().ShouldBe(null); } [TestMethod] public void LogInfoMessagesWhenInfoEnabled() { //arrange var logManager = GetLogManager(Level.Info); //act logManager.Info(LOG_MESSAGE); //assert GetLogMessage().ShouldBe(LOG_MESSAGE); } [TestMethod] public void LogInfoMessagesWithExceptionWhenInfoEnabled() { //arrange var logManager = GetLogManager(Level.Info); //act logManager.Info(LOG_MESSAGE, _exception); //assert GetLogMessage().ShouldBe(LOG_MESSAGE); GetLogException().ShouldBe(GetLogExceptionMessage()); } [TestMethod] public void NotLogInfoMessagesWhenInfoDisabled() { //arrange var logManager = GetLogManager(Level.Warn); //act logManager.Info(LOG_MESSAGE); //assert GetLogMessage().ShouldBe(null); } [TestMethod] public void LogWarnMessagesWhenWarnEnabled() { //arrange var logManager = GetLogManager(Level.Warn); //act logManager.Warn(LOG_MESSAGE); //assert GetLogMessage().ShouldBe(LOG_MESSAGE); } [TestMethod] public void LogWarnMessagesWithExceptionWhenWarnEnabled() { //arrange var logManager = GetLogManager(Level.Warn); //act logManager.Warn(LOG_MESSAGE, _exception); //assert GetLogMessage().ShouldBe(LOG_MESSAGE); GetLogException().ShouldBe(GetLogExceptionMessage()); } [TestMethod] public void NotLogWarnMessagesWhenWarnDisabled() { //arrange var logManager = GetLogManager(Level.Error); //act logManager.Warn(LOG_MESSAGE); //assert GetLogMessage().ShouldBe(null); } [TestMethod] public void LogErrorMessagesWhenErrorEnabled() { //arrange var logManager = GetLogManager(Level.Error); //act logManager.Error(LOG_MESSAGE); //assert GetLogMessage().ShouldBe(LOG_MESSAGE); } [TestMethod] public void LogErrorMessagesWithExceptionWhenErrorEnabled() { //arrange var logManager = GetLogManager(Level.Error); //act logManager.Error(LOG_MESSAGE, _exception); //assert GetLogMessage().ShouldBe(LOG_MESSAGE); GetLogException().ShouldBe(GetLogExceptionMessage()); } [TestMethod] public void NotLogErrorMessagesWhenErrorDisabled() { //arrange var logManager = GetLogManager(Level.Fatal); //act logManager.Error(LOG_MESSAGE); //assert GetLogMessage().ShouldBe(null); } [TestMethod] public void LogFatalMessagesWhenFatalEnabled() { //arrange var logManager = GetLogManager(Level.Fatal); //act logManager.Fatal(LOG_MESSAGE); //assert GetLogMessage().ShouldBe(LOG_MESSAGE); } [TestMethod] public void LogFatalMessagesWithExceptionWhenFatalEnabled() { //arrange var logManager = GetLogManager(Level.Fatal); //act logManager.Fatal(LOG_MESSAGE, _exception); //assert GetLogMessage().ShouldBe(LOG_MESSAGE); GetLogException().ShouldBe(GetLogExceptionMessage()); } [TestMethod] public void NotLogFatalMessagesWhenOff() { //arrange var logManager = GetLogManager(Level.Off); //act logManager.Fatal(LOG_MESSAGE); //assert GetLogMessage().ShouldBe(null); } private ILogManager GetLogManager(Level level) { _appender = new MemoryAppender { Name = "Unit Testing Appender", Layout = new log4net.Layout.PatternLayout("%message"), Threshold = level }; _appender.ActivateOptions(); var root = ((Hierarchy)log4net.LogManager.GetRepository()).Root; root.AddAppender(_appender); root.Repository.Configured = true; var rootLogger = log4net.LogManager.GetLogger("root"); return new LogManager(rootLogger); } private string GetLogMessage() { if (_appender.GetEvents().Length == 0) return null; var logEvent = _appender.GetEvents()[0]; return logEvent.MessageObject.ToString(); } private string GetLogException() { if (_appender.GetEvents().Length == 0) return null; var logEvent = _appender.GetEvents()[0]; return logEvent.ExceptionObject.ToString(); } private string GetLogExceptionMessage() { return string.Format("{0}: {1}", _exception.GetType().FullName, _exception.Message); } }
Happy coding!