2009-10-05 16 views
23

log4netを使用するコンポーネントがあります。私は単体テストを作成し、特定のエラー条件が正しいロギングになることを検証したい。log4netでログアペンダーをプログラムで追加および削除する

これを行う最善の方法は、モックのようなILogAppenderの実装を作成することだと考えていました。私は、テストセットアップ中にlog4netにログアペンダーを追加し、テストの検証中に書き込まれたものを検査し、テストティアダウン中に再度削除します。

これは可能ですか?

答えて

11

をlog4netのアペンダを追加および削除の問題を解決しなければなりません。このアペンダーを使用すると、テスト中に記録されたインメモリーメッセージにアクセスできます。

+0

私はついにこれを実装しました。問題は非常にうまく解決します。 – Pete

+0

+1; 'ILog'のスタブ実装を私のクラスの全てに注入することを避けました:-) –

3

次のコードは、私はMemoryAppenderで構成the BasicConfiguratorを使用している元々apache mailing list archivesに見つかりました、コード

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

BasicConfiguratorまたはXmlConfiguratorをどこにも使用しない場合、log4netが実際に何かを実行するようにするには、Hierarchy.Configuredをtrueに設定する必要があることに注意してください。 – Vivelin

19

BasicConfiguratorを使用することは、単体テスト(OPが要求したもので、件名に含まれていないもの)では問題ありません。他の回答は、特定のロガーの出力を取得します。

私はそれがすべて(これはウェブサイト内の「自己テスト」ページでした)でした。

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

...しかし、パヴェルのアプローチ@ごとのような使い捨て

UPDATEとして包ま:最後に、私は基本的に以下のなかったパヴェルの答えが削除されたので、私はここに彼のリンクを追加してい: をProgrammatically check Log4Net log

1

方法について:アドオンのため

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

同じ。

+0

アドインを実際に動作させる方法を知っていますか?私が作成したカスタムアペンダの実装をテストするための単体テストを作成しましたが、LogManager.GetLogger(string)が返すILog実装にはアペンダの読み取り専用コレクションがあるため、残念ながらLoggerのAddメソッドはうそです。それは内部的にスローする例外を静かに消費し、アペンダーを実際に追加することはありません。 –