Handling Complex Fake or Test Data When Unit Testing-Builder Pattern

The data supporting the unit tests you are creating may have classes that contain other classes as properties. Here we have a Person class that contains an Address class

public class Person{
	public string FirstName {get;set;} 
	public string LastName {get;set;}
	public Address Address{get;set;}
}

public class Address{
	public string Address1{get;set;}
	public string PostCode{get;set;}
	public string Country{get;set;}
}

There are a number of possible scenarios to be unit tested, i.e. If the address is missing or invalid or missing person details. For each unit test the test objects will need to be created which could easily result in duplicate or just tedious typing. For example objects similar to the one below may need to be created with slightly different data for each test.

var person = new Person{
	FirstName="Joe",
	LastName="Bloggs",
	Address=new Address{
		Address1="1 The Grove",
		PostCode="PembroVille",
		Country="United Kingdom"	
	}
};

A real life scenario could involve more complex classes than this example resulting in more tedious duplication. One useful trick is to create a builder class to easily build objects that cater for different test scenarios. In this builder class you can configure the data for each different positive and negative test with the advantages of configure once, reusable code.
Below is a PersonBuilder class which aids in building a Person object with different data relevant to the tests being performed.

public class PersonBuilder
{
    private Person _person = new Person();

    public Person Build(){
        // Set standard default values for properties here if needed
        return _person;
    }

    public PersonBuilder WithValidDetails()
    {
        _person.FirstName="Joe";
        _person.LastName="Bloggs";
        return this;
    }

    public PersonBuilder WithValidAddress()
    {
        _person.Address=new Address{
            Address1="1 The Grove",
            PostCode="PembroVille",
            Country="United Kingdom"
        };
        return this;
    }
	
    public PersonBuilder WithInValidAddress()
    {
        _person.Address=null;
        return this;
    }
}

I can build an empty Person

	var person = new PersonBuilder().WithValidDetails().Build();

A Person with valid details and an valid address

var person = new PersonBuilder().WithValidDetails().WithValidAddress().Build();

This is a somewhat simplified example which would work easily well with complex classes.