Reputation: 499
I want to use autofixture to create an object graph where children have a reference to the parent object. For example :
class A
{
public List<B> Children { get; set; }
}
class B
{
public A Parent { get; set; }
}
I tried to make a behavior that handles the recursion, but I don't know how to emit the parent object as the content of the property.
public class AutoParentOnRecursionBehavior : ISpecimenBuilderTransformation
{
public ISpecimenBuilder Transform(ISpecimenBuilder builder)
{
if (builder == null)
throw new ArgumentNullException("builder");
return new RecursionGuard(builder, new AutoParentOnRecursionHandler());
}
}
public class AutoParentOnRecursionHandler : IRecursionHandler
{
public object HandleRecursiveRequest(
object request,
IEnumerable<object> recordedRequests)
{
object handleRecursiveRequest = recordedRequests.First(x => x.Equals(request));
return ....
}
}
Thanks.
Edit : I am thinking of a generic way, without having to specify the types A and B or even the property Children. For all properties of a property type that contains the object, set them to the parent object. In other words all properties of a type that trigger the recursion guard set them to the last object in the creation hierarchy.
Upvotes: 3
Views: 1363
Reputation: 174329
My answer assumes that
B.Parent
should be null
if you create B
directly. B.Parent
should be set to the instance of A
that contains it, if you create A
.This can be achieved with the following rather simple customizations when using PostProcessorFor:
fixture.Customize<B>(c => c.Without(x => x.Parent));
fixture.PostProcessorFor<A>(a => { foreach(var b in a.Children) b.Parent = a; });
Some asserts to illustrate the result:
var b = fixture.Create<B>();
Assert.Null(b.Parent);
var a = fixture.Create<A>();
Assert.True(a.Children.All(b => ReferenceEquals(b.Parent, a)));
Upvotes: 3