2009-10-05 10 views
23

Mam komponent, który używa log4net. Chcę utworzyć testy jednostkowe, które sprawdzą, czy pewne warunki błędu prowadzą do prawidłowego logowania.Programowe dodawanie i usuwanie rejestratorów dzienników w log4net

Myślałem, że najlepszym sposobem na zrobienie tego jest stworzenie implementacji ILogAppender, na przykład makiety. Dodałbym wtedy logownika do log4net podczas konfiguracji testowej, sprawdził, co zostało napisane podczas sprawdzania poprawności testu, i usunął go ponownie podczas testowanego odrzucenia.

Czy to możliwe?

Odpowiedz

11

Używam the BasicConfigurator skonfigurowany z MemoryAppender. Ten program pozwala uzyskać dostęp do komunikatów zapisanych w pamięci podczas testu.

+0

W końcu muszę to wdrożyć i bardzo dobrze rozwiązuje problem – Pete

+0

+1; uratował mnie przed wykonaniem kodu pośredniego 'ILog' i wstrzyknięciem go na wszystkie moje zajęcia :-) –

3

Poniższy kod został pierwotnie znaleźć na apache mailing list archives i powinno rozwiązać problem dodawania i usuwania appenders log4net w kodzie

/// <summary> 
/// dataLog 
/// </summary> 
protected static readonly IDeviceCommunicationsLog dataLog = 
DeviceCommunicationsLogManager.GetLogger("LIS3.Data"); 


Each connection adds and removes a file appender programmatically: 

/// <summary> 
/// add connection specific appender 
/// </summary> 
void AddAppender() 
{ 
    // check if logging is endabled 
    if(this.IsLoggingEnabled()) 
    { 
     try 
     { 
      // get the interface 
      IAppenderAttachable connectionAppender = (IAppenderAttachable)this.DataLog.Logger; 
      // need some application configuration settings 
      NameValueCollection appSettings = ConfigurationSettings.AppSettings; 
      // get the layout string 
      string log4netLayoutString = appSettings["log4net.LIS3.LayoutString"]; 
      if(log4netLayoutString == null) 
      { 
       // use default setting 
       log4netLayoutString = "%d [%x]%n %m%n %P MessageData}%n%n"; 
      } 
      // get logging path 
      string log4netPath = appSettings["log4net.Path"]; 
      if(log4netPath == null) 
      { 
       // use default path 
       log4netPath = ".\\"; 
      } 
      // create the appender 
      this.rollingFileAppender = new RollingFileAppender(); 
      // setup the appender 
      this.rollingFileAppender.MaxFileSize = 10000000; 
      this.rollingFileAppender.MaxSizeRollBackups = 2; 
      this.rollingFileAppender.RollingStyle = RollingFileAppender.RollingMode.Size; 
      this.rollingFileAppender.StaticLogFileName = true; 
      string appenderPath = LogSourceName + ".log"; 
      // log source name may have a colon - if soreplace with underscore 
      appenderPath = appenderPath.Replace(':', '_'); 
      // now add to log4net path 
      appenderPath = Path.Combine(log4netPath, appenderPath); 
      // update file property of appender 
      this.rollingFileAppender.File = appenderPath; 
      // add the layout 
      PatternLayout patternLayout = new PatternLayout( log4netLayoutString); 
      this.rollingFileAppender.Layout = patternLayout; 
      // add the filter for the log source 
      NDCFilter sourceFilter = new NDCFilter(); 
      sourceFilter.StringToMatch = this.LogSourceName; 
      this.rollingFileAppender.AddFilter(sourceFilter); 
      // now add the deny all filter to end of the chain 
      DenyAllFilter denyAllFilter = new DenyAllFilter(); 
      this.rollingFileAppender.AddFilter(denyAllFilter); 
      // activate the options 
      this.rollingFileAppender.ActivateOptions(); 
      // add the appender 
      connectionAppender.AddAppender(this.rollingFileAppender); 
     } 
     catch(Exception x) 
     { 
      this.ErrorLog.Error("Error creating LIS3 data log appender for " + LogSourceName, x); 
     } 
    } 
} 
/// <summary> 
/// remove connection specific appender 
/// </summary> 
void RemoveAppender() 
{ 
    // check if we have one 
    if(this.rollingFileAppender != null) 
    { 
     // cast to required interface 
     IAppenderAttachable connectionAppender = (IAppenderAttachable)this.DataLog.Logger; 
     // remove the appendier 
     connectionAppender.RemoveAppender(rollingFileAppender); 
     // set to null 
     this.rollingFileAppender = null; 
    } 
} 
+0

Jeśli nie korzystasz z BasicConfigurator lub XmlConfigurator w dowolnym miejscu, musisz ustawić Hierarchy.Configured na wartość true, aby log4net rzeczywiście zrobił cokolwiek. – Vivelin

19

Korzystanie z BasicConfigurator jest dobre dla testowania jednostkowego (o co prosił OP, ale nie o to, co jest w temacie). Pozostałe odpowiedzi wychwytują dane wyjściowe dla określonego rejestratora.

Ja chciałem to wszystko (to była strona "autotest" na stronie internetowej). W końcu zrobiłem w zasadzie następujące:

var root = ((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root; 
var attachable = root as IAppenderAttachable; 

var appender = new log4net.Appender.MemoryAppender(); 
if(attachable!=null) 
    attachable.AddAppender(appender); 
// do stuff 
var loggingEvents = appender.GetEvents(); 
foreach (var loggingEvent in loggingEvents) 
    loggingEvent.WriteRenderedMessage(writer); 
if(attachable!=null) 
    attachable.RemoveAppender(appender); 

... ale opakowane jako jednorazowe, jak na @ podejściem Pawła

UPDATE: odpowiedź Pawła został usunięty, więc dodaję swój odnośnik tutaj: Programmatically check Log4Net log.

1

Jak o:

((log4net.Repository.Hierarchy.Logger) theLogger.Logger).RemoveAppender("SomeAppender"); 

sama dla dodatku.

+0

Czy wiesz, jak sprawić, by dodawanie faktycznie działało? Napisałem test jednostkowy, aby przetestować implementację niestandardowego aplikatora, który stworzyłem, ale niestety metoda Add Logger jest kłamstwem, ponieważ implementacja ILog, którą LogManager.GetLogger (string) zwraca, ma kolekcję appenderów tylko do odczytu. Kończy się po cichu pochłanianie wyjątku, który rzuca wewnętrznie i nigdy tak naprawdę nie dodaje dodatku. –

Powiązane problemy