テスト作成パターン(AutOfixture)のTDDシステム
-
01-10-2019 - |
質問
私は使用しようとしています SUTファクトリー 私のsutを作成する「パターン」。
SUT構造を考えると:
namespace MySut
{
public class Dep1
{
}
public class Dep2
{
}
public class Sut
{
public Sut( Dep1 dep1, Dep2 dep2 )
{
}
}
}
私は使用しています オートフィックス, 、そして、次の仕様と関連する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つのものをock笑することができるが、依存するオブジェクトの作成を持たずにカスタマイズできるようにすることができる方法依存関係のセットが変更されるたびに、SUTコンストラクターへの明示的な呼び出しを再検討します。
(xunit.net(subspec style)、moq、ninject2を使用します(ただし、私の仕様ではDIを使用したくない))
解決
オートフィクストールは、余分な足場なしで、あなたのためにこのすべてを多少行うことができます。私は基本的なフィクスチャから始めて、それを使用して解決します Sut
:
var fixture = new Fixture();
var sut = fixture.CreateAnonymous<Sut>();
これはそれを前提としています Dep1
と Dep2
Autofixtureによって自動的に作成できますが、提示されているように、デフォルトのコンストラクターがあるためにできます。
特定のタイプをオーバーライドする場合は、次のようなレジスタメソッドを使用できます。
var fixture = new Fixture();
var mock = new Mock<Dep1>();
fixture.Register(mock.Object);
// Setup mock if necessary...
var sut = fixture.CreateAnonymous<Sut>();
これは原因です fixture
使用する mock.Object
いつでも Dep1
いつを含め、必要です Sut
コンストラクターが呼び出されます。これは、進化するコンストラクターに直面して堅牢であるというあなたの要件に間違いなく適合し、そのようにオートフィックスチュールが構築された主な理由の1つです。
より現実的なシナリオでは、DEP1とDEP2はインターフェイスである可能性があります。その場合、「デフォルトのフィクスチャ」の一部としてそれらを登録することをお勧めします。これは確かにおそらくそれだからです 登録する最後の呼び出しは勝ちます. 。これは、いくつかの優れたデフォルトでフィクスチャインスタンスを構成し、これを行う必要がある場合はいつでも特定のタイプをオーバーライドできることを意味します。
私は個人的に自動フィクストールを自動モックコンテナとして使用しています。 この議論 Autofixture 1.1 APIでこれがどのように可能かについてのヒントを提供しますが、AutoFixture 2.0の新しいカーネルは、はるかに優れた拡張性オプションを提供します。私がそれに到達したら、このテーマに関するブログ投稿を書きます。
PS返信が遅れて申し訳ありませんが、今まであなたの質問は見られませんでした。将来的には、より速い返信を得るために(Twitterで)私(Twitterで)を自由にpingしてください。