Tricks with Test Data Builders: Emphase the Domain Model with Factory Methods
Tests that use Test Data Builders can be made less noisy by combining builders. This still leaves some noise in the test: the test code overly emphasises how the tests are building objects at the expense of what they are building. A future reader of the test will be far more interested in what objects are being used than in the way that those objects are constructed.
We can de-emphasise the builders further by instantiating them in clearly named factory methods:
Order order = anOrder().fromCustomer( aCustomer().withAddress( anAddress().withNoPostcode())).build();
When we do this, the naming convention we've used for builder methods up to now gets in the way instead of making things clearer. The builder code looks better if we rename the methods to reflect the relationship between objects only, and not include the type of object at the far end of the relationship:
Order order = anOrder().from(aCustomer().with(anAddress().withNoPostcode())).build();
This relies on Java's method overloading and so only works for properties that have unique, user-defined types. Longer method names are necessary for primitive types, or if the built object has different relationships with the same type of object. For example, most of the fields of an Address are Strings, and so the builder methods must be explicitly named after the field. However, the post code is strongly typed and so can be passed to an overloaded method:
Address aLongerAddress = anAddress() .withStreet("222b Baker Street") .withCity("London") .with(postCode("NW1", "3RX")) .build();