Create a fixture for recursive data structure with AutoFixture
<p>I'm working on a project where I have some recursive data structure and I want to create a fixture for it.</p>

<p>The data structure is <code>XmlCommandElement</code>, it has a single method <code>ToCommand</code> that converts <code>XmlCommandElement</code> to <code>Command</code>.</p>

<p>Each node on the tree can be a <code>XmlCommandElement</code> and/or <code>XmlCommandPropertyElement</code>.</p>

<p>Now, in order to test the behaviour of the method <code>ToCommand</code> I want to fetch <code>XmlCommandElement</code> with some arbitrary data.</p>

<p>I want to control the depth of the tree and the amount of instances of <code>XmlCommandElement</code> and/or <code>XmlCommandPropertyElement</code> per node.</p>

<p><strong>So here is the code I'm using for the fixture:</strong></p>

<pre><code>public class XmlCommandElementFixture : ICustomization
{
    private static readonly Fixture _fixture = new Fixture();

    private XmlCommandElement _xmlCommandElement;

    public int MaxCommandsPerDepth { get; set; }

    public int MaxDepth { get; set; }

    public int MaxPropertiesPerCommand { get; set; }

    public XmlCommandElementFixture BuildCommandTree()
    {
        _xmlCommandElement = new XmlCommandElement();

        var tree = new Stack&lt;XmlCommandElementNode&gt;();

        tree.Push(new XmlCommandElementNode(0, _xmlCommandElement));

        while (tree.Count &gt; 0) {
            var node = tree.Pop();
            node.Command.Key = CreateRandomString();
            node.Command.Properties = CreateProperties();

            if (MaxDepth &gt; node.Depth) {
                var commands = new List&lt;XmlCommandElement&gt;();

                for (var i = 0; i &lt; MaxCommandsPerDepth; i++) {
                    var command = new XmlCommandElement();
                    tree.Push(new XmlCommandElementNode(node.Depth + 1, command));
                    commands.Add(command);
                }

                node.Command.Commands = commands.ToArray();
            }
        }

        return this;
    }

    public void Customize(IFixture fixture)
    {
        fixture.Customize&lt;XmlCommandElement&gt;(c =&gt; c.FromFactory(() =&gt; _xmlCommandElement)
                                                   .OmitAutoProperties());
    }

    private static string CreateRandomString()
    {
        return _fixture.Create&lt;Generator&lt;string&gt;&gt;().First();
    }

    private XmlCommandPropertyElement[] CreateProperties()
    {
        var properties = new List&lt;XmlCommandPropertyElement&gt;();

        for (var i = 0; i &lt; MaxPropertiesPerCommand; i++) {
            properties.Add(new XmlCommandPropertyElement {
                Key = CreateRandomString(),
                Value = CreateRandomString()
            });
        }

        return properties.ToArray();
    }

    private struct XmlCommandElementNode
    {
        public XmlCommandElementNode(int depth, XmlCommandElement xmlCommandElement)
        {
            Depth = depth;

            Command = xmlCommandElement;
        }

        public XmlCommandElement Command { get; }

        public int Depth { get; }
    }
}
</code></pre>

<p><strong>And this is how I'm using it:</strong></p>

<pre><code>xmlCommandElement = new Fixture().Customize(new XmlCommandElementFixture {
    MaxDepth = 2,
    MaxCommandsPerDepth = 3,
    MaxPropertiesPerCommand = 4
}.BuildCommandTree()).Create&lt;XmlCommandElement&gt;();
</code></pre>

<p>This works perfectly fine! but the issue I have with it is it isn't <em>generic</em>, the whole point of AutoFixture at least as far as I know is to avoid making specific fixtures.</p>

<p>So what I would really like to do is something like this (found it <a href="https://stackoverflow.com/questions/31855842/how-do-i-customize-autofixture-behaviours-for-specific-classes">here</a> but it doesn't work for me.):</p>

<pre><code>var fixture = new Fixture();
fixture.Behaviors.OfType&lt;ThrowingRecursionBehavior&gt;()
       .ToList()
       .ForEach(b =&gt; fixture.Behaviors.Remove(b));
fixture.Behaviors.Add(new DepthThrowingRecursionBehavior(2));
fixture.Behaviors.Add(new OmitOnRecursionForRequestBehavior(typeof(XmlCommandElement), 3));
fixture.Behaviors.Add(new OmitOnRecursionForRequestBehavior(typeof(XmlCommandPropertyElement), 4));

xmlCommandElement = fixture.Create&lt;XmlCommandElement&gt;();
</code></pre>

<p><strong>Here is all the code for reference:</strong></p>

<p><strong>Interfaces:</strong></p>

<pre><code>public interface ICommandCollection : IEnumerable&lt;ICommand&gt;
{
    ICommand this[string commandName] { get; }

    void Add(ICommand command);
}

public interface ICommandPropertyCollection : IEnumerable&lt;ICommandProperty&gt;
{
    string this[string key] { get; }

    void Add(ICommandProperty property);
}

public interface ICommandProperty
{
    string Key { get; }

    string Value { get; }
}

public interface ICommand
{
    ICommandCollection Children { get; set; }

    string Key { get; }

    ICommandPropertyCollection Properties { get; }
}

public interface ICommandConvertible
{
    ICommand ToCommand();
}
</code></pre>

<p><strong>Classes:</strong></p>

<pre><code>public sealed class CommandPropertyCollection : ICommandPropertyCollection
{
    private readonly IDictionary&lt;string, ICommandProperty&gt; _properties;

    public CommandPropertyCollection()
    {
        _properties = new ConcurrentDictionary&lt;string, ICommandProperty&gt;();
    }

    public string this[string key]
    {
        get
        {
            ICommandProperty property = null;

            _properties.TryGetValue(key, out property);

            return property.Value;
        }
    }

    public void Add(ICommandProperty property)
    {
        _properties.Add(property.Key, property);
    }

    public IEnumerator&lt;ICommandProperty&gt; GetEnumerator()
    {
        return _properties.Values.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public sealed class CommandProperty : ICommandProperty
{
    public CommandProperty(string key, string value)
    {
        Key = key;

        Value = value;
    }

    public string Key { get; }

    public string Value { get; }
}

public sealed class Command : ICommand
{
    public Command(string key, ICommandPropertyCollection properties)
    {
        Key = key;

        Properties = properties;
    }

    public ICommandCollection Children { get; set; }

    public string Key { get; }

    public ICommandPropertyCollection Properties { get; }
}

public class XmlCommandPropertyElement : ICommandPropertyConvertible
{
    [XmlAttribute("key")]
    public string Key { get; set; }

    [XmlAttribute("value")]
    public string Value { get; set; }

    public ICommandProperty ToCommandProperty()
    {
        return new CommandProperty(Key, Value);
    }
}
</code></pre>

<p><strong>Finally, the class I'm trying to test is as follow:</strong></p>

<pre><code>public class XmlCommandElement : ICommandConvertible
{
    [XmlArray]
    [XmlArrayItem("Command", typeof(XmlCommandElement))]
    public XmlCommandElement[] Commands { get; set; }

    [XmlAttribute("key")]
    public string Key { get; set; }

    [XmlArray]
    [XmlArrayItem("Property", typeof(XmlCommandPropertyElement))]
    public XmlCommandPropertyElement[] Properties { get; set; }

    public ICommand ToCommand()
    {
        ICommandPropertyCollection properties = new CommandPropertyCollection();

        foreach (var property in Properties) {
            properties.Add(property.ToCommandProperty());
        }

        ICommand command = new Command(Key, properties);

        return command;
    }
}
</code></pre>

<p><strong>The test itself looks like this:</strong></p>

<pre><code>namespace Yalla.Tests.Commands
{
    using Fixtures;

    using FluentAssertions;

    using Ploeh.AutoFixture;

    using Xbehave;

    using Yalla.Commands;
    using Yalla.Commands.Xml;

    public class XmlCommandElementTests
    {
        [Scenario]
        public void ConvertToCommand(XmlCommandElement xmlCommandElement, ICommand command)
        {
            $"Given an {nameof(XmlCommandElement)}"
                .x(() =&gt;
                {
                    xmlCommandElement = new Fixture().Customize(new XmlCommandElementFixture {
                        MaxDepth = 2,
                        MaxCommandsPerDepth = 3,
                        MaxPropertiesPerCommand = 4
                    }.BuildCommandTree()).Create&lt;XmlCommandElement&gt;();
                });

            $"When the object is converted into {nameof(ICommand)}"
                .x(() =&gt; command = xmlCommandElement.ToCommand());

            "Then we need to have a root object with a key"
                .x(() =&gt; command.Key.Should().NotBeNullOrEmpty());

            "And 4 properties as its children"
                .x(() =&gt; command.Properties.Should().HaveCount(4));
        }
    }
}
</code></pre>

<p><strong>Thanks to Mark Seemann! the final solution looks like this:</strong></p>

<pre><code>public class RecursiveCustomization : ICustomization
{
    public int MaxDepth { get; set; }

    public int MaxElements { get; set; }

    public void Customize(IFixture fixture)
    {
        fixture.Behaviors
               .OfType&lt;ThrowingRecursionBehavior&gt;()
               .ToList()
               .ForEach(b =&gt; fixture.Behaviors.Remove(b));
        fixture.Behaviors.Add(new OmitOnRecursionBehavior(MaxDepth));
        fixture.RepeatCount = MaxElements;
    }
}
</code></pre>

<p><strong>And can be used like this:</strong></p>

<pre><code>xmlCommandElement = new Fixture().Customize(new RecursiveCustomization {
    MaxDepth = 2,
    MaxElements = 3
}).Create&lt;XmlCommandElement&gt;();
</code></pre>