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

Alternatively, you could mock the calls to the constructed objects.
In this case though, that probably leads to specs that are too tightly
coupled to the implementation.

I know this seems like kind of a cop-out, but you'll get much better
results if you BDD this from scratch.  If this is super complex legacy
stuff, just try to get some semi-high level tests around it (the sort
of test I showed would work fine), and then you can refactor it.

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

Reply via email to