11

単体テストでメソッドが呼び出されているかどうかを確認するために Moq を使用しています。この特定のケースでは、テスト対象のメソッドが log4net を介してエラーをログに記録するかどうかをテストしたいと考えています。log.Error問題は、これは、またはを呼び出すことによって実行できることlog.ErrorFormatです。どちらでも構いません。

どうすればこれを確認できますか?両方が呼び出されたことを確認する方法しか知りません。

var logMock = new Mock<ILog>();

var myClass = new MyClass(logMock.Object);

myClass.MyMethod();

logMock.Verify(log => log.Error(It.IsAny<object>()));
logMock.Verify(log => log.ErrorFormat(It.IsAny<string>(), It.IsAny<object>()));

考えてみると、どちらにもたくさんのオーバーロードがあり、いずれかのオーバーロードが呼び出されてもかまいません (これが良いテストであることに疑いを持ち始めています)。

前もって感謝します。

編集:私は厄介なことを考えました:

try
{
    logMock.Verify(log => log.Error(It.IsAny<object>()));
}
catch (Moq.MockException ex)
{
    logMock.Verify(log => log.ErrorFormat(It.IsAny<string>(), It.IsAny<object>()));
}

多分私はある種の拡張メソッドでこれをラップすることができます...例えばVerifyAny.

4

2 に答える 2

14

フラグを設定する有効なエラーメソッドごとにコールバックを登録できます。

// Arrange
bool errorFlag = false;
logMock
    .Setup(l => l.Error(It.IsAny<object>()))
    .Callback((object o) => errorFlag = true);

/* repeat setup for each logMock method */

// Act
myClass.MyMethod();

// Assert
Assert.IsTrue(errorFlag);

もちろん、カバーする過負荷がたくさんある場合、これはまだ面倒です。

編集:そして楽しみのために、ここに拡張メソッドがありMock<T>.VerifyAnyます:

public static class MockExtensions
{
    public static void VerifyAny<T>(this Mock<T> mock, params Expression<Action<T>>[] expressions)
        where T: class
    {
        List<MockException> exceptions = new List<MockException>();
        bool success = false;
        foreach (var expression in expressions)
        {
            try
            {
                mock.Verify(expression);
                success = true;
                break;
            }
            catch (MockException ex)
            {
                exceptions.Add(ex);
            }
        }

        if (!success)
        {
            throw new AggregateException("None of the specified methods were invoked.", exceptions);
        }
    }
}

使用法:

[TestMethod]
public void FooTest()
{
    Mock<IFoo> fooMock = new Mock<IFoo>();
    fooMock.Object.Bar1();

    fooMock.VerifyAny(
        f => f.Bar1(),
        f => f.Bar2());
}
于 2013-01-10T00:20:04.057 に答える
1

特定のエラーがログに記録されたことを具体的にテストしている場合は、2 つのテストが必要です。1 つは確実にlog.Error呼び出されるテストで、もう 1 つは確実に呼び出されるテストlog.ErrorFormatです。

それでもどちらかを確認したい場合は、このアプローチを使用するだけで、必要なことを正確に実行できます。

単体テストでいずれかのメソッドが呼び出されたことを確認する

于 2013-01-10T00:24:39.743 に答える