log4netを使用するコンポーネントがあります。私は単体テストを作成し、特定のエラー条件が正しいロギングになることを検証したい。log4netでログアペンダーをプログラムで追加および削除する
これを行う最善の方法は、モックのようなILogAppenderの実装を作成することだと考えていました。私は、テストセットアップ中にlog4netにログアペンダーを追加し、テストの検証中に書き込まれたものを検査し、テストティアダウン中に再度削除します。
これは可能ですか?
log4netを使用するコンポーネントがあります。私は単体テストを作成し、特定のエラー条件が正しいロギングになることを検証したい。log4netでログアペンダーをプログラムで追加および削除する
これを行う最善の方法は、モックのようなILogAppenderの実装を作成することだと考えていました。私は、テストセットアップ中にlog4netにログアペンダーを追加し、テストの検証中に書き込まれたものを検査し、テストティアダウン中に再度削除します。
これは可能ですか?
をlog4netのアペンダを追加および削除の問題を解決しなければなりません。このアペンダーを使用すると、テスト中に記録されたインメモリーメッセージにアクセスできます。
次のコードは、私は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;
}
}
BasicConfiguratorまたはXmlConfiguratorをどこにも使用しない場合、log4netが実際に何かを実行するようにするには、Hierarchy.Configuredをtrueに設定する必要があることに注意してください。 – Vivelin
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。
方法について:アドオンのため
((log4net.Repository.Hierarchy.Logger) theLogger.Logger).RemoveAppender("SomeAppender");
同じ。
アドインを実際に動作させる方法を知っていますか?私が作成したカスタムアペンダの実装をテストするための単体テストを作成しましたが、LogManager.GetLogger(string)が返すILog実装にはアペンダの読み取り専用コレクションがあるため、残念ながらLoggerのAddメソッドはうそです。それは内部的にスローする例外を静かに消費し、アペンダーを実際に追加することはありません。 –
私はついにこれを実装しました。問題は非常にうまく解決します。 – Pete
+1; 'ILog'のスタブ実装を私のクラスの全てに注入することを避けました:-) –