Let me start by saying I'm a huge fan of the elegance of this pattern -- I have a group of basic entities that I have implemented builders for (specifically for testing). However I have found (and this may be the caveat) that as my program evolved I kept having to go back and re-work the builders. In the end, it really hasn't seemed worth it to keep them updated, and I've gone back to primarily keeping a Object Mother that has a lot of pre-configured entities. Should I continue to update the builders for future use, or is the TDBs something that should only be created once you're design has reached some stability and the Object Mother becomes too large?
Also note, I've found I'm not using the builders anywhere else in the app, as I enjoy using .Net 3.0 's new syntax for property initialization.
I like using fluent builders for the object under test to express the nature of the object I'm creating. ObjectMothers tend to get unwieldy and tend to (in the implementations I've come across) end up hiding details of the objects creation.
Compare:
User fred = CreateUser("fred").WithReputation(900)
.WithScholarBadge()
.WithCriticBadge()
vs:
User fred = UserObjectMother.Fred()
To express the idea that the user has rep 900 and those two particular badges would be unweildy to do with the ObjectMother. The tendecy I've seen is developers then finding this method that builds Fred()
, which is close to what they need so they add more attributes to the object. The fluent builder on the other hand is expressive as to what is being built, and is easy to create specific users for the test as required.
That said, I also end up using these patterns exclusively in test code as the production code does not usually require this sort of expressiveness.
If the test data builders become too complex to maintain, I would recommend switching to a mocking framework, which makes it more convenient to produce domain test objects with a known state.
Moreover with mocks you could make the test objects be more than simple stubs, and actually participate in what the test is asserting, by setting expectations on how their properties and methods are invoked.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With