When @kluivers pointed out @klaaspieter's post on using the Builder Pattern in Objective-C I took note, as this is something I’d used quite extensively doing TDD in Java. I thought I saw a way to finesse it slightly and finally having had the time to do it, I’m happy to say it’s worked out like I’d hoped.
The idea was to use an Objective-C category to hide the builder-related code and prevent it from “polluting” the original implementation.
This gist has an example. Say I have some kind of “value item” class (
GroupableItem in this case) having a bunch of properties which all need values, most of which might not be germane to any given test and some of which might be complex to set up. I create a
GroupableItem+Builder category containing an implementation of a
GroupableItemBuilder class with properties for all the configurable options.
GroupableItemBuilder's init method sets default values for all the configurable properties of the builder. Finally, this category defines the
itemWithBlock class method, which creates the value object from the defaults set in the builder, after they’ve been “offered” to the user to change via the block.
This way in my
SomethingUsingGroupableItemTest I can import the category and use the builder to set whichever properties are relevant to my particular test, knowing I’ll always end up with an internally consistent object.
Better, if the
GroupableItem+Builder category is declared in my test tree, it isn’t even compiled into my app.
This is kind of a degenerate example and I could of course have just created a method in my test class with parameters for the configurable options that returned an instance of my value object. But this breaks down pretty quickly when you have more than three or four configurable properties (only one or two of which you might want to alter from the default for any given test.) It also creates a pleasing separation between the “meat” of the test and the “plumbing” (which can be easily reused in multiple places.) This approach is also type safe across refactorings of my value object’s property names.