Test Data Builders Refined

Last year, I blogged about Test Data Builders here and here. I still use them heavily in my unit tests for creating objects with test data. Heck, I also use this pattern for fluent interfaces in production code. Here is a simple example of this approach:

 

   1: public class CustomerBuilder
   2: {
   3:     public String _firstName = "Homer";
   4:     public String _lastName = "Simpson";
   5:         
   6:     public CustomerBuilder WithFirstName(String firstName)
   7:     {
   8:         _firstName = firstName;
   9:         return this;    
  10:     }
  11:  
  12:     public CustomerBuilder WithLastName(String lastName)
  13:     {
  14:         _lastName = lastName;
  15:         return this;
  16:     }
  17:         
  18:     public Customer Build()
  19:     {
  20:         return new Customer(_firstName, _lastName);    
  21:     }
  22: }

This fluent builder class can then be used this way:
   1: Customer customer = new CustomerBuilder()
   2:     .WithFirstName("Homer")
   3:     .WithLastName("Simpson")
   4:     .Build();

A while ago, Greg Young started a series of blog posts on DDDD (Distributed Domain-Driven Design), which I can highly recommend. Make sure to catch up now you still can because I think that he has a lot of stuff coming up, which I’m really looking forward to.

Anyhow, Greg had a couple of posts on fluent builders, which you can read here, here and here. I noticed an interesting approach in the way that the target object is built. Here is an example of this approach:

 

   1: public class CustomerBuilder
   2: {
   3:     public String _firstName = "Homer";
   4:     public String _lastName = "Simpson";
   5:         
   6:     public CustomerBuilder WithFirstName(String firstName)
   7:     {
   8:         _firstName = firstName;
   9:         return this;    
  10:     }
  11:  
  12:     public CustomerBuilder WithLastName(String lastName)
  13:     {
  14:         _lastName = lastName;
  15:         return this;
  16:     }
  17:         
  18:     public Customer Build()
  19:     {
  20:         return new Customer(_firstName, _lastName);    
  21:     }
  22:  
  23:     public static implicit operator Customer(
  24:         CustomerBuilder builder) 
  25:     {  
  26:         return builder.Build()    
  27:     } 
  28: }

which results in the following usage:

 

   1: Customer customer = new CustomerBuilder()
   2:     .WithFirstName("Homer")
   3:     .WithLastName("Simpson");

Adding an implicit cast operator to the builder class makes that its no longer required to explicitly call the Build method. I keep the Build method around for backwards-compatibility reasons or in case I ever need it again (violating YAGNI in the process, I know, I know). I find that adding the implicit cast operator adds to the readability of the fluent interface, don’t you agree?

Published by

Jan Van Ryswyck

Hi, thank you for visiting my blog and reading all the crap that I'm posting here. I'm a senior software engineer at SD WORX. Developing software is one of my greatest passions in life, and I enjoy doing it every single day. I've got three kids (Len, Lisa & Laura) who constantly remind me that there is more in life than just programming all day. They are the greatest kids in the whole world. And last but not least, there's my girlfriend who is my inspiration in life. You can always contact me at jan_dot_van_dot_ryswyck at gmail.com

6 thoughts on “Test Data Builders Refined”

Comments are closed.