web-dev-qa-db-ja.com

検証を使用してMoqモッククラスで期待されるパラメーター値を確認する

モック内のメソッドが、予想されるオブジェクトパラメーターで呼び出されることを確認しようとしています。私はMoq、nUnitを使用しており、AutoFixtureのLikenessが仕事を成し遂げるべきだと考えています。以下は、私がやろうとしていることの簡易版です。

AutoFixtureでこれを行う方法はありますか? Somethingが適切なパラメーターで呼び出されることを確認するより良い方法はありますか?

AクラスのEqualsをオーバーライドしてプロパティ値を比較し、Verify行を次のように変更します。

barMock.Verify(m => m.Something(a));

ただし、プロジェクトのAのようなすべてのクラスでEqualsをオーバーライドしたくないです。

namespace Test
{
    using Moq;
    using NUnit.Framework;
    using Ploeh.SemanticComparison.Fluent;

    public class A
    {
        public int P1 { get; set; }
    }
    public interface IBar
    {
        void Something(A a);
    }

    public class Foo
    {
        public A Data { get; private set; }
        public void DoSomethingWith(IBar bar)
        {
            Data = new A { P1 = 1 };
            bar.Something(Data);
        }
    }

    [TestFixture]
    public class AutoFixtureTest
    {
        [Test]
        public void TestSample()
        {
            var foo = new Foo();
            var barMock = new Mock<IBar>();
            var a = new A { P1 = 1 };
            var expectedA = a.AsSource().OfLikeness<A>();

            foo.DoSomethingWith(barMock.Object);

            expectedA.ShouldEqual(foo.Data);   // passes
            barMock.Verify(m => m.Something(expectedA.Value));  // fails
        }
    }
}
45
jaminto

Verify Moqでは、デフォルトで引数の参照の等価性をチェックするので、テストと実装で同じインスタンスを提供する場合(Equalsをオーバーライドした場合を除く)にのみ渡されます。

あなたの場合、expectedA.Valueは、テストで作成されたnew A { P1 = 1 }を返すだけです。もちろん、DoSomethingWithで作成されたインスタンスとは異なります。

MoqのIt.Isコンストラクトを使用して、Equalsをオーバーライドせずにこれを適切にテストする必要があります(実際、Autofixtureはまったく必要ありません)。

barMock.Verify(m => m.Something(It.Is<A>(arg => arg.P1 == a.P1)));

ただし、P1、P2、P3などの複数のプロパティがある場合は、AutoFixtureが便利です。

barMock.Verify(m => m.Something(It.Is<A>(arg => expectedA.Equals(a))));

すべてのプロパティの等価性チェックを手動で書き出す必要がないためです。

70
nemesv

AutoFixture 2.9.1(またはそれ以降)にアップグレードする場合、LikenessインスタンスでCreateProxyメソッドを呼び出して、宛先タイプの動的プロキシを発行できます。

生成された動的プロキシは、Likenessを使用してEqualsをオーバーライドし、構文を単純化します(非常に多く)。

Likenessプロキシを使用するように変更された元のテストメソッドは次のとおりです。

[Test]
public void TestSample()
{
    var foo = new Foo();
    var barMock = new Mock<IBar>();
    var expected = new A().AsSource().OfLikeness<A>().CreateProxy();
    expected.P1 = 1;

    foo.DoSomethingWith(barMock.Object);

    Assert.True(expected.Equals(foo.Data));     // passes
    barMock.Verify(m => m.Something(expected)); // passes
}

また、テストアサーションは、Anyインスタンスを受け入れるよりもはるかに具体的になることに注意してください。

この新機能の詳細については、こちらをご覧ください こちら

5
Nikos Baxevanis