Configure AutoFixure Using FromSeed Causees Exception

For two classes:

class Foo { ... } class Bar { public Foo FooBar { get; set; } } 

I installed the following test:

 void Test() { var fixture = new Fixture(); fixture.Customize<Foo>(x => x.FromSeed(TestFooFactory)); var fooWithoutSeed = fixture.Create<Foo>(); var fooWithSeed = fixture.Create<Foo>(new Foo()); var bar = fixture.Create<Bar>(); //error occurs here } Foo TestFooFactory(Foo seed) { //do something with seed... return new Foo(); } 

I can create Foo objects directly and without initial values โ€‹โ€‹without any problems. But as soon as I try to create a Bar object that has a Foo property, I get an ObjectCreationException :

The decorated ISpecimenBuilder could not create a pattern for: Foo. This can happen if the request is an interface or an abstract class; if so, register with ISpecimenBuilder, which can create samples based on the request. If this happens in a strongly typed Build expression, try providing the factory with one of the IFactoryComposer methods.

I expect TestFooFactory get a null TestFooFactory initial value at the time of Bar creation, just like when I created Foo without an initial value. Am I doing something wrong, or could it be a mistake?

In my real-world scenario, I want to configure how AutoFixture will use the sown values โ€‹โ€‹for certain objects when I pass nested values, but I still want AutoFixture to default to normal if the seed is not provided.

+5
source share
1 answer

How do you configure Fixture to use the initial values correctly .

The behavior you see is a consequence of how the FromSeed setting changes the AutoFixture pipeline. If you are interested in knowing the details, I described them here .

As a workaround, you can use a custom instance for seed queries, such as:

 public class RelaxedSeededFactory<T> : ISpecimenBuilder { private readonly Func<T, T> create; public RelaxedSeededFactory(Func<T, T> factory) { this.create = factory; } public object Create(object request, ISpecimenContext context) { if (request != null && request.Equals(typeof(T))) { return this.create(default(T)); } var seededRequest = request as SeededRequest; if (seededRequest == null) { return new NoSpecimen(request); } if (!seededRequest.Request.Equals(typeof(T))) { return new NoSpecimen(request); } if ((seededRequest.Seed != null) && !(seededRequest.Seed is T)) { return new NoSpecimen(request); } var seed = (T)seededRequest.Seed; return this.create(seed); } } 

Then you can use it to create objects of type Foo as follows:

 fixture.Customize<Foo>(c => c.FromFactory( new RelaxedSeededFactory<Foo>(TestFooFactory))); 

This setting will pass default(Foo) - this is null - as the start of the TestFooFactory factory function when populating properties of type Foo .

+5
source

Source: https://habr.com/ru/post/1235626/


All Articles