我有一个具有多个构造函数的数据类型,我需要 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 置于 Customization 中,它会覆盖所有默认创建策略,包括用于字符串的策略。相反,它会寻找最贪婪的字符串构造函数,即:
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());
那应该行得通。