强制AutoFixture使用最贪婪的构造函数

我有一个包含多个构造函数的数据类型,我需要AutoFixture来选择最贪婪的(一个参数最多的)。 默认行为是选择编号最小的构造函数。

作者的博客文章http://blog.ploeh.dk/2009/03/24/HowAutoFixtureCreatesObjects.aspx似乎并不意味着有一种方法可以覆盖这种行为,所以它是否可能,如果是这样,如何?

这当然是可能的 。

要更改单个类型( MyClass )的策略:

 fixture.Customize(c => c.FromFactory( new MethodInvoker( new GreedyConstructorQuery()))); 

全面改变策略:

 fixture.Customizations.Add( new MethodInvoker( new GreedyConstructorQuery())); 

然而,事实certificate,使用GreedyConstructorQuery全面使用很可能是有问题的,如下面的代码片段所示。 想象一下这个构造函数的类:

 public Foo(string name) { this.name = name; } 

此测试将抛出exception:

 [Test] public void GreedyConstructor() { Fixture fixture = new Fixture(); fixture.Customizations.Add(new MethodInvoker(new GreedyConstructorQuery())); Foo foo = fixture.CreateAnonymous(); } 

抛出的exception是:

Ploeh.AutoFixture.ObjectCreationException:AutoFixture无法从System.SByte *创建实例,很可能是因为它没有公共构造函数,是抽象或非公共类型。

那么关于SByte *的是什么? 在Foo中没有SByte *

嗯,是的。 通过将MethodInvoker置于Customization中,它将覆盖所有默认创建策略,包括用于字符串的策略。 相反,它寻找字符串最贪婪的构造函数,那就是:

 public String(sbyte* value, int startIndex, int length, Encoding enc); 

还有sbyte * ……


用贪婪的算法替换适度的构造函数选择算法仍然是可能的,它比我最初意识到的要多一点。

你能做的是:

写一个像这样的小class:

 public class GreedyEngineParts : DefaultEngineParts { public override IEnumerator 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()); 

这应该工作。