複数のコンストラクターを持つデータ型があり、最も貪欲なもの(パラメーターが最も多いもの)を選択するにはAutoFixtureが必要です。デフォルトの動作では、最小数のコンストラクターを選択します。
著者のブログ投稿http://blog.ploeh.dk/2009/03/24/HowAutoFixtureCreatesObjects.aspxは、この動作をオーバーライドする方法があることを示唆していないようです。そのため、それは可能ですか。
複数のコンストラクターを持つデータ型があり、最も貪欲なもの(パラメーターが最も多いもの)を選択するにはAutoFixtureが必要です。デフォルトの動作では、最小数のコンストラクターを選択します。
著者のブログ投稿http://blog.ploeh.dk/2009/03/24/HowAutoFixtureCreatesObjects.aspxは、この動作をオーバーライドする方法があることを示唆していないようです。そのため、それは可能ですか。
これは確かに可能です。
単一タイプの戦略を変更するには(MyClass
):
fixture.Customize<MyClass>(c => c.FromFactory(
new MethodInvoker(
new GreedyConstructorQuery())));
戦略を全面的に変更するには:
fixture.Customizations.Add(
new MethodInvoker(
new GreedyConstructorQuery()));
ただし、次のコードスニペットが示すように、GreedyConstructorQueryを全面的に使用すると、問題が発生する可能性が高くなります。このコンストラクターを持つクラスを想像してみてください。
public Foo(string name)
{
this.name = name;
}
このテストは例外をスローします:
[Test]
public void GreedyConstructor()
{
Fixture fixture = new Fixture();
fixture.Customizations.Add(new MethodInvoker(new GreedyConstructorQuery()));
Foo foo = fixture.CreateAnonymous<Foo>();
}
スローされる例外は次のとおりです。
Ploeh.AutoFixture.ObjectCreationException:AutoFixtureはSystem.SByte *からインスタンスを作成できませんでした。おそらく、パブリックコンストラクターがないため、抽象型または非パブリック型です。
では、SByte*についてはどうでしょうか。FooにはSByte*はありません...
ええ、そうです。MethodInvokerをカスタマイズに配置することにより、文字列の作成戦略を含む、すべてのデフォルトの作成戦略を上書きします。代わりに、文字列の最も貪欲なコンストラクターを探します。つまり、次のようになります。
public String(sbyte* value, int startIndex, int length, Encoding enc);
そして、sbyte*があります...
控えめなコンストラクター選択アルゴリズムを欲張りアルゴリズムに置き換えることはまだ可能です。それは私が最初に気付いたよりも少し複雑です。
あなたができることはこれです:
次のような小さなクラスを作成します。
public class GreedyEngineParts : DefaultEngineParts
{
public override IEnumerator<ISpecimenBuilder> GetEnumerator()
{
var iter = base.GetEnumerator();
while (iter.MoveNext())
{
if (iter.Current is MethodInvoker)
yield return new MethodInvoker(
new CompositeMethodQuery(
new GreedyConstructorQuery(),
new FactoryMethodQuery()));
else
yield return iter.Current;
}
}
}
次のようにFixtureインスタンスを作成します。
Fixture fixture = new Fixture(new GreedyEngineParts());
それはうまくいくはずです。