On Mar 25, 2008, at 12:04 AM, Pat Maddox wrote:
> On Mon, Mar 24, 2008 at 6:50 PM, Chuck Remes  
> <[EMAIL PROTECTED]> wrote:
>> So I have a complex object that I need to construct. This complex
>> object, at runtime, takes an object in its initializer. The
>> initializer interrogates the object and creates several collaborative
>> objects based upon values from that interrogation.
>>
>> The construction is complicated enough that it pretty much begs to be
>> implemented via the Builder Pattern.
>>
>> My problem is that I don't know how to test this behavior regardless
>> of whether the object handles its own construction or I create a
>> separate Builder object to construct it for me.
>>
>> For example:
>>
>> class ComplexObjectBuilder
>>   def initialize
>>     @complex_object = ComplexObject.new
>>   end
>>
>>   def create_foo(control, value)
>>     case control do
>>     when :a then @complex_object.foo = SpecialObject.new(value * 4)
>>     when :v then @complex_object.foo = OtherObject.new
>>     when :z then @complex_object.foo = YAObject.new
>>     end
>>   end
>>
>>   def create_bar(control, value)
>>     # similar to above
>>   end
>>
>>   def construct
>>     # some business rules to make sure the object is complete; use
>>     # defaults for fields that were not set via the interface
>>     return @complex_object
>>   end
>> end
>>
>> @builder = ComplexObjectBuilder.new
>> @builder.create_foo(params_object.accessor1, params_object.accessor2)
>> @builder.create_bar(params_object.accessor3, params_object.accessor4)
>> baz = @builder.construct
>>
>> How the heck do I test anything here?  I do not see how I can  
>> validate
>> the behavior of #create_foo or #create_bar without exposing
>> @complex_object via a public interface. Those #create_* methods are
>> purely for construction and do not return a value. Only #construct
>> returns a value which should be the completed object
>>
>> Is there a transformation to consider to make this more testable?
>>
>> I'm hoping someone has tackled this before and can provide me some
>> insight. Many thanks...
>>
>> cr
>
> Hey Chuck,
>
> I would toss whatever code you have and BDD it from scratch.
> Shouldn't be that difficult...you can start off with stuff like
>
> describe ComplexObjectBuilder, " when foo is built with :a" do
>  before(:each) do
>    builder = ComplexObjectBuilder.new
>    builder.create_foo :a, 3
>    @built = builder.construct
>  end
>  it "should create a special object" do
>    @built.foo.should be_a(SpecialObject)
>  end
>
>  it "should quadruple the value passed to the special object" do
>    @built.foo.some_val.should == 12
>  end
> end
>

Pat,

thanks for your response.

I have question regarding your suggestion. In the first "it" you are  
asserting that @built.foo should be an object. The @built instance  
variable is the ComplexObject and not the ComplexObjectBuilder.  
Shouldn't we be testing the behavior of the builder and not the  
ComplexObject the builder produces? Another way, shouldn't I put the  
ComplexObject assertions into its own set of specs?

It just seems like we're mixing the behavior of two objects here:  
ComplexObjectBuilder and ComplexObject. Perhaps that is okay since  
they are so tightly coupled. In a sense the ComplexObjectBuilder is  
just a fancy constructor for the other object; it only gets refactored  
out to its own object because it has so many parts/steps.

??

cr

_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to