title: Create a fixture for recursive data structure with AutoFixture
body: <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>