8

The domain model I am working with has a lot of circular references. In fact it is possible to get to most objects from any point in the graph. Many of these circular references are also in collections. So a Booking will have a collection of Students which has a collection of Courses which has a collection of Bookings and so on. This is not the real model, just an example. The problem is caused by a combination of around thirty different classes.

To work with this model I am configuring and using AutoFixture like so

var fixture = new Fixture().Customize(new MultipleCustomization());
fixture.Behaviors.Remove(new ThrowingRecursionBehavior());
fixture.Behaviors.Add(new OmitOnRecursionBehavior());

var booking = fixture.CreateAnonymous<Booking>();

This causes AutoFixture to run for about twenty minutes until it finally fails with an OutOfMemoryException.

Is this model asking AutoFixture to create an infinite graph which can never end? If so, is there any way I can configure it to limit the depth of the graph?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Keith Bloom
  • 2,391
  • 3
  • 18
  • 30
  • 3
    20 minutes... That's a long time, but I'd still guess it's a recursion issue. FWIW, AutoFixture was always created and intended as a TDD tool, so the intent has always been that to the degree it can detect a recursion, this is feedback about the design of the SUT. This should prompt the programmer to stop and consider alternatives to circular references. – Mark Seemann Oct 04 '12 at 12:49
  • This makes sense and I would like to remove those circular references. For this scenario then would I be better sign fixture.Build.With(x => x.Thing).OmitAutoProperties() until I can remover the circular references? – Keith Bloom Oct 04 '12 at 14:35
  • Yes, that's one option. If you can provide a repro, I'll see if I can do anything with the issue you report, but right now I don't know how to reproduce it. – Mark Seemann Oct 04 '12 at 15:37
  • Of course, it is hard to check without something to go on. Is it OK if I email something to you? – Keith Bloom Oct 04 '12 at 19:39
  • I don't mind an email, but if at all possible I'd prefer a public repro, because then other AutoFixture collaborators would have a chance of taking on the issue as well. Currently I'm a bit short on time...https://github.com/AutoFixture/AutoFixture/issues?state=open – Mark Seemann Oct 05 '12 at 07:33
  • Thanks. I will put a repro on GitHub. – Keith Bloom Oct 05 '12 at 08:08

1 Answers1

0

I realize this is an old question, but for anybody finding this, I think the behaviour of OmitOnRecursionBehaviour might have changed (or been fixed :-). It defaults to a recursion depth of 1.

And you can specify the recursionDepth. If this is set too deep, it results in an StackOverflowException though, not an OutOfMemoryException, at least for me.

Anyways, here is a simple example.

void Main()
{   
    var fixture = new Fixture();
    fixture
        .Behaviors
        .OfType<ThrowingRecursionBehavior>()
        .ToList()
        .ForEach(b => fixture.Behaviors.Remove(b));
        
    fixture.Behaviors.Add(new OmitOnRecursionBehavior(10));
    var node = fixture.Create<Node>();      
    
    Console.WriteLine($"It goes {HowDeepDoesItGo(node)} levels down");  
    // Outputs:
    //     It goes 10 levels down
    // With OmitOnRecursionBehavior(), without the recursionDepth argument, then outputs:
    //     It goes 1 levels down
}

int HowDeepDoesItGo(Node node, int level = 1)
{
    if (node.Link is null) return level;
    return HowDeepDoesItGo(node.Link, level + 1);
}

public class Node
{   
    public Node Link { get; init;}
}
Magnus
  • 353
  • 3
  • 8