How AutoFixture Creates Objects by Mark Seemann
As we previously saw, the CreateAnonymous method can create a new instance of a type known to it only from its type parameter:
MyClass sut = fixture.CreateAnonymous<MyClass>();
AutoFixture was never compiled with any knowledge of the MyClass type, so it obviously uses Reflection to create the instance. That's hardly surprising in itself.
In the case of MyClass, it has a default constructor, so creating an instance is as simple as it can be, but what happens if we instead ask for a more complex instance?
As an example, the ComplexParent type has this constructor:
public ComplexParent(ComplexChild child)
ComplexChild, however, has two constructors:
public ComplexChild(string name)
public ComplexChild(string name, int number)
So what happens when we ask AutoFixture to create an instance of ComplexParent?
ComplexParent only has a single public constructor, so AutoFixture doesn't have any other choice than picking that. This means that it must now create an anonymous instance of ComplexChild.
Fortunately, AutoFixture's raison d'être is creating objects, so creating an instance of ComplexChild isn't a big deal; the only thing it needs to figure out is which constructor to pick. When multiple public constructors are available, it always picks the one with the fewest number of arguments - in this case ComplexChild(string).
Obviously, it then needs to create an anonymous string value. For primitive types like strings, numbers and booleans, AutoFixture has custom algorithms for value creation. Since I'll cover those mechanisms later, suffice it to say that Constrained Non-Determinism is used to create an anonymous string.
At this point, AutoFixture has all the information it needs, and it can now return a properly initialized instance of ComplexParent.
This ability to create instances of almost arbitrarily complex types is a real time-saver: That, more than the ability to create single strings or numbers, was the reason I originally created AutoFixture, since I got tired of initializing complex object graphs just to satisfy some API that the Test Fixture requires.
It also has the additional advantage that it hides all the irrelevant object creation code that the Test Fixture needs, but which isn't relevant for the test at hand.