c# autofixture

c# - Fuerza a AutoFixture a usar el constructor más codicioso



(1)

Esto es ciertamente posible .

Para cambiar la estrategia para un solo tipo ( MyClass ):

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

Para cambiar la estrategia en general:

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

Sin embargo, resulta que el uso de GreedyConstructorQuery en todos los ámbitos es probablemente problemático, como lo demuestra el siguiente fragmento de código. Imagina una clase con este constructor:

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

Esta prueba arrojará una excepción:

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

La excepción lanzada es:

Ploeh.AutoFixture.ObjectCreationException: AutoFixture no pudo crear una instancia desde System.SByte *, probablemente porque no tiene un constructor público, es un tipo abstracto o no público.

Entonces, ¿qué es eso del SByte *? No hay SByte * en Foo ...

Bueno, sí que hay. Al colocar el MethodInvoker en la personalización, anula todas las estrategias de creación predeterminadas, incluida la de las cadenas. En su lugar, va en busca del constructor más codicioso para la cadena y es:

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

Y ahí está el sbyte * ...

Todavía es posible reemplazar el modesto algoritmo de selección de constructores con un algoritmo codicioso, es solo un poco más complicado de lo que creía.

Lo que puedes hacer es esto:

Escribe una clase pequeña como esta:

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; } } }

y crea la instancia del Fixture como esta:

Fixture fixture = new Fixture(new GreedyEngineParts());

Eso debería funcionar.

Tengo un tipo de datos con varios constructores y necesito AutoFixture para elegir el más codicioso (uno con la mayoría de los parámetros). El comportamiento predeterminado es elegir el constructor con el número más pequeño.

La publicación del blog del autor, http://blog.ploeh.dk/2009/03/24/HowAutoFixtureCreatesObjects.aspx no parece implicar que haya una manera de anular este comportamiento, así que es posible, y si es así, ¿cómo?