Gal Segal's Blog

Thoughts of a programmer with a soul

Dec 10

Unit Testing Log4Net Wrapper

Tags:

writing

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!

Back to top