このエラーの解決策は数日間私を逃れました、そして助けのためにここに来る時が来ました。短いバージョンは、ビルドサーバーで失敗する単体テストがありますが、他の環境では失敗しません。
私がテストしているメソッドは、log4netのILogの拡張メソッドです。この拡張メソッドの目的は、呼び出されたときに現在のメソッドのデバッグログを作成し、それをデバッグに使用することです。これを行うためのコードは非常に簡単です。
public static void MethodHead(this ILog log, params object[] parameters)
{
/* Assert */
log.AssertNonNull();
/* Since this is an expensive operation, don't do it if Debug is not enabled */
if (log.IsDebugEnabled)
{
StackTrace stackTrace = new StackTrace();
/* Get calling method */
MethodBase method = stackTrace.GetFrame(1).GetMethod();
string logMessage = string.Format("{0}.{1}({2})", method.DeclaringType.Name, method.Name, parameters.ToDelimitedString(", "));
log.Debug(logMessage);
}
}
この方法では、デバッグモードが有効になっていることを確認します。これは、ログに記録されるものがない場合はStackTraceを実行したくないためです(パフォーマンスの問題のため)。このメソッドをテストするときは、Rhino Mocksを使用してILogインターフェイスをモックし、IsDebugEnabledがtrueを返すようにします。
次のNUnitテスト方法を検討してください。
[Test(Description = "Verify that MethodHead extension method will log with calling class.method(arguments)")]
public void MethodHeadShouldLogCurrentMethodNameWithArguments()
{
/* Setup */
MockRepository mocks = new MockRepository();
ILog log = mocks.CreateMock<ILog>();
string[] arguments = new string[] { "CAT", "IN", "A", "HAT" };
string logMessage = string.Format("{0}.{1}({2})",
"MethodHeadTest", "CallingMethod", arguments.ToDelimitedString(", "));
With.Mocks(mocks).Expecting(delegate
{
/* Record */
Expect.Call(log.IsDebugEnabled).Return(true);
Expect.Call(delegate { log.Debug(logMessage); });
})
.Verify(delegate
{
/* Verify */
CallingMethod(log, arguments);
});
}
private void CallingMethod(ILog log, params object[] arguments)
{
log.MethodHead(arguments);
}
これは、私の開発環境であるVisualStudio2008とTestDriven.NETでうまく実行されます。nunit-console.exeまたはnunit-guiを使用してテストを実行すると、正常に実行されます。NAntスクリプトを使用してテストを実行すると、正常に実行されます。
ただし、CruiseControl.NETから実行されるNAntを介して実行すると、ビルドサーバーはこのテストに失敗します。ビルドサーバーでnunit-console.exeを使用して手動で実行すると、成功します。
エラーとスタックトレースは次のとおりです。
Rhino.Mocks.Exceptions.ExpectationViolationException : ILog.Debug("**<>c__DisplayClass8.<MethodHeadShouldLogCurrentMethodNameWithArguments>b__5**(CAT, IN, A, HAT)"); Expected #0, Actual #1.
ILog.Debug("MethodHeadTest.CallingMethod(CAT, IN, A, HAT)"); Expected #1, Actual #0.
at Rhino.Mocks.MethodRecorders.UnorderedMethodRecorder.DoGetRecordedExpectation(IInvocation invocation, Object proxy, MethodInfo method, Object[] args)
at Rhino.Mocks.MethodRecorders.MethodRecorderBase.GetRecordedExpectation(IInvocation invocation, Object proxy, MethodInfo method, Object[] args)
at Rhino.Mocks.Impl.ReplayMockState.DoMethodCall(IInvocation invocation, MethodInfo method, Object[] args)
at Rhino.Mocks.Impl.ReplayMockState.MethodCall(IInvocation invocation, MethodInfo method, Object[] args)
at Rhino.Mocks.MockRepository.MethodCall(IInvocation invocation, Object proxy, MethodInfo method, Object[] args)
at Rhino.Mocks.Impl.RhinoInterceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at ILogProxy86e676a4761d4509b43a354c1aba33ed.Debug(Object message)
at Vanilla.Extensions.LogExtensions.MethodHead(ILog log, Object[] parameters) in d:\Build\Mint\WorkingDirectory\Source\Main\Vanilla\Extensions\LogExtensions.cs:line 42
at Vanilla.UnitTests.Extensions.LogExtensions.MethodHeadTest.<>c__DisplayClass8.<MethodHeadShouldLogCurrentMethodNameWithArguments>b__5() in d:\Build\Mint\WorkingDirectory\Source\Test\Vanilla.UnitTests\Extensions\LogExtensions\MethodHeadTest.cs:line 99
at Rhino.Mocks.With.FluentMocker.Verify(Proc methodCallsToBeVerified)
at Vanilla.UnitTests.Extensions.LogExtensions.MethodHeadTest.MethodHeadShouldLogCurrentMethodNameWithArguments() in d:\Build\Mint\WorkingDirectory\Source\Test\Vanilla.UnitTests\Extensions\LogExtensions\MethodHeadTest.cs:line 90
したがって、問題は、ビルドサーバーがこのメソッドに別の(動的?)名前があると見なすことです。それとも、この仮定を行うのはRhino Mocksですか?
開発マシンで再作成できないため、このエラーは発生しません。私は私が得ることができるすべての入力に満足しています。
ありがとうございました!
ミカエル・ルンディン