Blog

Test Data Builder versus Object Mother

September 30, 2007

When writing unit tests, I frequently have an issue with creating objects that contain some test data. One approach is to call the constructor of the class at hand in every test case, like so:

[Test]
public void TestCase1()
{
        Customer customer = new Customer("Homer", "Simpson");
        // further implementation
}

[Test]
public void TestCase2()
{
        Customer customer = new Customer(null, "Simpson");
        // further implementation
}

[Test]
public void TestCase3()
{
        Customer customer = new Customer("Homer", null);
        // further implementation
}

The problem with this approach becomes clear when adding a new argument to the constructor of the Customer class. Now I have to make a change to all tests that create a Customer object.

What I did to overcome this issue, was to use the Object Mother pattern. I created a static class called TestFactory with a bunch of constant fields and methods that create all kinds of objects: 

internal static class TestFactory
{
    public const String FirstName = "Homer";
    public const String LastName = "Simpson";
    
    private static Customer CreateCustomer(String firstName, 
                                          String lastName)
    {
        return new Customer(firstName, lastName);
    }

    public static Customer CreateValidCustomer()
    {
        return CreateCustomer(FirstName, LastName);
    }

    public static Customer CreateCustomerWithoutFirstName()
    {
        return CreateCustomer(null, LastName);
    }

    public static Customer CreateCustomerWithoutLastName()
    {
        return CreateCustomer(FirstName, null);
    }
}

I didn't really like this approach. For every special case, I needed to add another factory method. I couldn't come up with something better either at the time, so ... until I read this fine article yesterday. Instead of using the Object Mother pattern, the author uses the Builder pattern.

public class CustomerBuilder
{
    public String _firstName = "Homer";
    public String _lastName = "Simpson";
        
    public CustomerBuilder WithFirstName(String firstName)
    {
        _firstName = firstName;
        return this;    
    }

    public CustomerBuilder WithLastName(String lastName)
    {
        _lastName = lastName;
        return this;
    }
        
    public Customer Build()
    {
        return new Customer(_firstName, _lastName);    
    }
}

The tests itself would look like this:

[Test]
public void TestCase1()
{
        Customer customer = new CustomerBuilder().Build();

        // further implementation
}

[Test]
public void TestCase2()
{
        Customer customer = new CustomerBuilder()
                                .WithFirstName(null)
                                .Build();

        // further implementation
}

[Test]
public void TestCase3()
{
        Customer customer = new CustomerBuilder()
                                 .WithLastName(null)
                                 .Build();

        // further implementation
}

Looks pretty neat huh? If you're interested in writing maintainable unit tests, then you should definitely give the article a good read. The examples are written in Java, so I don't know if that has got anything to do with it :-).

Profile picture of Jan Van Ryswyck

Jan Van Ryswyck

Thank you for visiting my blog. I’m a professional software developer since Y2K. A blogger since Y2K+5. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.

Comments

About

Thank you for visiting my website. I’m a professional software developer since Y2K. A blogger since Y2K+5. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.

Contact information

(+32) 496 38 00 82

infonull@nullprincipal-itnull.be