2009-10-05 17 views
23

Ho un componente che utilizza log4net. Voglio creare unit test, che convalidano che determinate condizioni di errore portano alla registrazione corretta.Aggiunta e rimozione di log in log4net in modo logico

Stavo pensando che il modo migliore per farlo è creare un'implementazione di ILogAppender, ad esempio una simulazione. Aggiungerei l'appender del log a log4net durante l'installazione del test, ispezionare ciò che è stato scritto durante la convalida del test e rimuoverlo di nuovo durante il test teardown.

È possibile?

risposta

11

Sono stato con the BasicConfigurator configurato con un MemoryAppender. Questo appender ti consente di accedere ai messaggi in memoria registrati durante il test.

+0

Ho finalmente ottenuto l'implementazione di questo, e risolve il problema molto piacevolmente – Pete

+0

+1; mi ha salvato dal realizzare un'implementazione stub di 'ILog' e l'ho iniettato in tutte le mie classi :-) –

3

Il seguente codice si trovava originariamente sulla apache mailing list archives e dovrebbe risolvere il problema di aggiunta e rimozione appenders log4net nel codice

/// <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

Si noti che se non si utilizza BasicConfigurator o XmlConfigurator ovunque, è necessario impostare Hierarchy.Configured su true per fare in modo che log4net esegua effettivamente qualsiasi operazione. – Vivelin

19

L'uso di BasicConfigurator va bene per il test dell'unità (cosa richiesto dall'OP, ma non cosa è nella riga dell'oggetto). Le altre risposte catturano l'output per un logger specifico.

Lo volevo all (questa era una pagina di "autotest" all'interno di un sito Web). Alla fine ho fatto fondamentalmente la seguente:

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); 

... ma avvolto come un usa e getta come da @ approccio di Pawel

UPDATE: La risposta di Pawel stato cancellato, quindi sto aggiungendo il suo link qui: Programmatically check Log4Net log.

1

ne dite:

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

stesso per aggiungere.

+0

Sai come rendere effettivamente funzionante l'aggiunta? Ho scritto un test unitario per testare l'implementazione di un appender personalizzato che ho creato, ma sfortunatamente il metodo Add di Logger è una bugia, perché l'implementazione di ILog che LogManager.GetLogger (stringa) restituisce ha una raccolta di appenders di sola lettura. Finisce consumando silenziosamente l'eccezione che getta internamente e non aggiunge mai realmente l'appender. –

Problemi correlati