Mark Needham

Thoughts on Software Development

C#: Builder pattern still useful for test data

with 17 comments

I had thought that with the ability to use the new object initalizer syntax in C# 3.0 meant that the builder pattern was now no longer necessary but some recent refactoring efforts have made me believe otherwise.

My original thought was that the builder pattern was really useful for providing a nicely chained way of creating objects, but after a bit of discussion with some colleagues I have come across three different reasons why we might want to use the builder pattern to create test data:

  • It creates a nice to read fluent interface describing the object being created. This argument holds more for Java rather than C# where we now have object initializers.
  • Domain objects are a bit complicated to create – encapsulate this logic in the builder.
  • We want to default non null data on some of the fields in our object. If we don’t explicitly set a value for a property in C# it defaults to null.

Even with the object initializer syntax we can still end up having to specify extra data that we don’t really care about in our test. The following is not uncommon:

new Foo {Bar = "bar", Baz = "baz", Bling = "bling"};
public class Foo
{
    public string Bar {get; set;}
    public string Baz { get; set; }
    public string Bling { get; set; }
}

Let’s say we only care about Bar for this test though but Baz and Bling are both being used in our code so we end up with a Null Reference Exception if we don’t set values for them. We can quickly end up having this redundant data being repeated across all our tests.

In steps the builder pattern!

new FooBuilder().Bar("bar").Build();
public class FooBuilder
{
    private string bar = "defaultBar";
    private string baz = "defaultBaz";
    private string bling = "defaultBling";
 
    public FooBuilder Bar(string value)
    {
        bar = value;
        return this;
    }
 
    public FooBuilder Baz(string value)
    {
        baz = value;
        return this;
    }
 
    public FooBuilder Bling(string value)
    {
        bling = value;
        return this;
    }
 
    public Foo Build()
    {
        return new Foo {Bar = bar, Baz = baz, Bling = bling};
    }
}

It takes a bit more code to setup but every time we use the builder it saves us typing in extra data that we don’t need.

It would be even better if we could not have to call that ‘Build’ method and we can get around this by using the implicit operator, the problem being that you need to apply it to the target class (i.e. Foo) rather than the class you want to implicitly convert from (i.e. FooBuilder).

I don’t really want to change a production code class just for test purposes so the ‘Build’ will have to stay in there for the time being.

Be Sociable, Share!

Written by Mark Needham

January 21st, 2009 at 11:49 pm

Posted in .NET

Tagged with ,

  • http://squirksoe.blogspot.com/ Rob Hunter

    Building objects like this is a lot more transparent in languages that support keyword parameters:

    #python
    foo = Foo(bar=”bar”)

    #ruby
    foo = Foo.new(:bar => “bar”)

    It’s very nice specify just what you care care about, and tell the reader what it is that you’re specifying.

    In my last couple of projects, I’ve enjoyed the use of the Machinist framework for building domain objects for integration tests.

    You give Machinst blueprints for your objects (using a convenient internal DSL), and Machinist builds an object graph whenever you want one, allowing you to override just the parts you are interested in.

  • http://blechie.com/wtilton Willie

    I don’t quite understand why you’d do this and not just get rid of the automatic get;set and just return a default instead.

    Like:

    private foo = “defaultFoo”;
    public string Foo {get { return foo; } set { foo = value; } }

    This way you could use the object initializer and have the same build pattern you’re talking about.

  • http://jroller.com/wipu Ville Oikarinen

    A fluent interface has also technical uses, besides pleasing the eye:

    http://web.sysart.fi/developer/articles:nested_fluent_builder

    In short: passing a fluent “sentence” around allows effective streaming of events, and the resulting code is beautiful.

    Here is a more complex example, a converter from a parsed Java AST to an ngrease element (tree). The fluent building sentence is IMHO piped nicely in and out from the AST visitor methods with absolutely no need for any state management:

    http://ngrease.svn.sourceforge.net/viewvc/ngrease/trunk/ngrease-java2ngr/src/main/java/net/sf/ngrease/java2ngr/Java2NgrConverter.java?view=markup

  • Pingback: Reflective Perspective - Chris Alcock » The Morning Brew #270

  • joe

    Why can’t you apply the implicit operator to the builder class so that you end up with

    public static implicit operator Foo(FooBuilder current)
    {
    return new Foo {Bar = bar, Baz = baz, Bling = bling};

    }

    Foo newFoo = new FooBuilder().Bar(“A”).Baz(“B”)

    How does require a change to a non-test class?

  • joe

    oops C&P error:

    return new Foo {Bar = current.bar, Baz = current.baz, Bling = current.bling};

  • http://www.markhneedham.com Mark Needham

    @joe I thought the implicit operator needs to go on the target class although just trying out what you suggested does seem to work which is really cool!

    I’m sure I tried that a few times before I posted and couldn’t get it to work but it certainly seems to work now – thanks for the tip

  • Pingback: TDD: Design tests for failure at Mark Needham

  • Pingback: Coding: Putting code where people can find it at Mark Needham

  • Pingback: Coding: Make it obvious at Mark Needham

  • Pingback: TDD: Keeping test intent when using test builders at Mark Needham

  • Philip Schwarz

    The second item in ‘Effective Java (2nd edition)’ is ‘Consider a builder when faced with many constructor parameters’.

    And this advice is aimed at all code, not just test code. One of the points Joshua Bloch makes is that rather than using the following

    NutritionFacts cocaCola = new NutritionFacts(240,8,100,0,35,27)

    which is hard to write, and harder still to read, we can us the builder pattern

    NutritionFacts cocaCola = NutritionFacts.Builder(240,8).calories(100).sodium(35).carbohydrate(27).build()

    which simulates named optional parameters (required parameters, e.g. 240 and 8, are passed in to the Builder’s constructor).

    The Builder is an inner class, so it is easy to locate.

  • Nitin

    One more advantage is, it allows user to plugin their own custom implementation into framework. Please refer the following blog.

    http://xeon2k.wordpress.com

  • http://codecrafter.blogspot.com Rodrigo Jordao

    I think you could still use the object initializer syntax for the builder. Just have the builder constructor do the value defaulting. Couple this with an implicit conversion operator and you get:

    Foo foo = new FooBuilder { Bar = “bar” };

  • Anonymous

    What you are really replacing here is the Setter pattern, not the Builder pattern.  The big difference is that with a builder I can have private variables within the object that are initialized via the builder, but then are immutable.  There is no set property and no chance of having the value changed down the road.  This can allow me the avoid situations where the object might be in an inconsistent state.

  • Pingback: TDD: Links, News and Resources (2) « Angel ”Java” Lopez on Blog

  • Pingback: TDD: Links, News And Resources (4) « Angel ”Java” Lopez on Blog