Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use value of a parent property when creating a complex child in AutoFixture

Tags:

c#

autofixture

I'm using AutoFixture to generate data for a structure involving a parent object and complex child objects, like this:

public class Parent
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Child[] Children { get; set; }
}

public class Child
{
    public string Name { get; set; }
    public int ParentId { get; set; }
}

Is there a way to automatically set the property ParentId of the generated Child object to the id assigned to the parent? Right now my solution looks like this, which isn't very pretty:

var parent = fixture.Build<Parent>().Without(p => p.Children).CreateAnonymous();
parent.Children = fixture.CreateMany<Child>(10).ToArray();

foreach (var i in parent.Children)
{
    i.ParentId = parent.Id;
}

It feels like there's a better way to do this that I am missing? I looked into creating a custom ISpecimenBuilder but didn't manage to solve it that way either.

like image 437
Niklas Söderberg Avatar asked Sep 06 '11 12:09

Niklas Söderberg


1 Answers

AutoFixture is based on a set of rules and assumptions about the API it may be asked to work with. Consider that it's been created and compiled without any prior knowledge of the Child and Parent classes, or any other types in a given API. All it has to work with is the public API.

Think of AutoFixture as a very dim programmer who doesn't even understand your language (not even English). The more fool-proof you can make your API, the easier it will be to use AutoFixture with it.

The problem with circular references like the Parent/Child relationship described here is that it breaks encapsulation. You'll need to create at least one of the class instances initially in an invalid state. That it's difficult to make AutoFixture work with such an API should mainly be taken as a warning sign that the API might benefit from refactoring.

Additionally, the .NET Framework Design Guidelines recommends against exposing arrays as properties - particularly writable properties. Thus, with a better encapsulated design, the API might be much easier to work with, both for AutoFixture and yourself and your colleagues.

Given the API above, I don't see any way this can be made much easier to work with. Consider how to remove the circular reference and make collection properties read-only, and it will be much easier.

For the record, I haven't written an API with a circular reference for years, so it's quite possible to avoid those Parent/Child relations.

like image 62
Mark Seemann Avatar answered Oct 09 '22 22:10

Mark Seemann