3

SUTファクトリの「パターン」を使用してSUTを作成しようとしています。

SUT構造が与えられた場合:

namespace MySut
{
    public class Dep1
    {
    }

    public class Dep2
    {
    }

    public class Sut
    {
        public Sut( Dep1 dep1, Dep2 dep2 )
        {
        }
    }
}

私はAutoFixtureを使用していますが、次の仕様と関連するSUTファクトリメソッド[貴重ですが]忙しい作業を折りたたむための最良の方法は何でしょうか。

namespace MySpecifications
{
    using MySut;
    public class MySpecification
    {
        public void TestCore()
        {
            // Dont care about dependencies, testing core functionality
            var sut = CreateSut();
        }

        public void TestDep1Interaction()
        {
            // Dont care about Dep2, want to observe stuff on the Dep1 dependent object
            var sut = CreateSut( new Mock<Dep1>().Object );
        }

        public void TestDep2Interaction()
        {
            // Dont care about Dep1, want to observe stuff on the Dep2 dependent object
            var sut = CreateSut( new Mock<Dep2>().Object );
        }

        private object CreateSut( )
        {
            return CreateSut( CreateDep1(), CreateDep2() );
        }

        private object CreateSut( Dep1 dep1 )
        {
            return CreateSut( dep1, CreateDep2() );
        }

        private object CreateSut( Dep2 dep2 )
        {
            return CreateSut( CreateDep1(), dep2 );
        }

        private Sut CreateSut( Dep1 dep1, Dep2 dep2 )
        {
            return new Sut( dep1, dep2 );
        }

        private static Dep1 CreateDep1()
        {
            return new Fixture().CreateAnonymous<Dep1>();
        }

        private static Dep2 CreateDep2()
        {
            return new Fixture().CreateAnonymous<Dep2>();
        }
    }
}

次のようなものに:

    public class MyAutoFixturedSpecification
    {
        public void TestCore()
        {
            // Dont care about dependencies, testing core functionality
            var sut = CreateSut();
        }

        public void TestDep1Interaction()
        {
            // Dont care about Dep2, want to observe stuff on the Dep1 dependent object
            var sut = CreateSut( new Mock<Dep1>().Object );
        }

        public void TestDep2Interaction()
        {
            // Dont care about Dep1, want to observe stuff on the Dep2 dependent object
            var sut = CreateSut( new Mock<Dep2>().Object );
        }

        private object CreateSut( params object[] injectedNonAnonymouses )
        {
            return new Fixture(  ).Build<Sut>(  )./*??????*/;
        }
    }

また:

    public class MyAnticipatedAutoFixturedSpecification
    {
        public void TestCore()
        {
            // Dont care about dependencies, testing core functionality
            var sut = new Fixture(  ).Build<Sut>().CreateAnonymous(  );
        }

        public void TestDep1Interaction()
        {
            // Dont care about Dep2, want to observe stuff on the Dep1 dependent object
            var sut = new Fixture().Build<Sut>()/*.With( new Mock<Dep1>().Object )*/.CreateAnonymous();
        }

        public void TestDep2Interaction()
        {
            // Dont care about Dep1, want to observe stuff on the Dep2 dependent object
            var sut = new Fixture().Build<Sut>()/*.With( new Mock<Dep2>().Object )*/.CreateAnonymous();
        }
    }

つまり、すべての工場のジャンクを削除して、私の仕様が次の状態への移行に簡単に対処できるようにします。

namespace MySutWithNewDependency
{
    public class Dep1
    {
    }

    public class Dep2
    {
    }

    public class Dep3
    {
    }

    public class Sut
    {
        public Sut( Dep1 dep1, Dep2 dep2, Dep3 dep3 )
        {
        }
    }
}

自動モッキングコンテナの概念と重複していますが、私はまだゴールデンハンマーを探していません-一度に0または1つのものをモックし、それでも依存オブジェクトの作成をカスタマイズできる方法です。依存関係のセットが変更されるたびに、Sutコンストラクターへの明示的な呼び出しを再検討します。

(xUnit.net(SubSpecスタイル)、Moq、Ninject2も使用しています(ただし、私の仕様ではDIを使用したくありません))

4

1 に答える 1

4

AutoFixtureは、余分な足場を一切使わずに、多かれ少なかれこれらすべてを実行できます。私は基本的なフィクスチャから始めて、それを使って解決しますSut

var fixture = new Fixture();
var sut = fixture.CreateAnonymous<Sut>();

これは、AutoFixtureによって自動的に作成できることを前提としてDep1いますが、提示されているように、デフォルトのコンストラクターがあるため作成できます。Dep2

特定のタイプをオーバーライドする場合は、次のようにRegisterメソッドを使用できます。

var fixture = new Fixture();

var mock = new Mock<Dep1>();
fixture.Register(mock.Object);
// Setup mock if necessary...

var sut = fixture.CreateAnonymous<Sut>();

これにより、コンストラクターが呼び出されたときを含め、必要なときにいつでもfixture使用できるようになります。これは、進化するコンストラクターに直面しても堅牢であるという要件に間違いなく適合し、AutoFixtureがそのように構築された主な理由の1つです。mock.ObjectDep1Sut

より現実的なシナリオでは、Dep1とDep2がインターフェースである可能性があります。その場合、それらを「デフォルトのフィクスチャ」の一部として登録することができます。これは確かに、Registerへの最後の呼び出しが勝ったためかもしれません。これは、いくつかの適切なデフォルトを使用してFixtureインスタンスを構成し、これを行う必要があるときはいつでも特定のタイプをオーバーライドできることを意味します。

私は個人的にAutoFixtureを自動モッキングコンテナとして使用しています。この説明は、AutoFixture 1.1 APIでこれがどのように可能になるかについてのヒントを提供しますが、AutoFixture 2.0の新しいカーネルは、はるかに優れた拡張オプションを提供します。それに到達したら、このテーマに関するブログ投稿を書きます。

PS返信が遅れて申し訳ありませんが、今まであなたの質問を見ていませんでした。将来的には、より迅速な返信のために、遠慮なく私にpingを送信してください(Twitterなど)。

于 2010-07-07T03:24:01.083 に答える