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