[rspec-users] Stubbing through multiple layers

David Chelimsky dchelimsky at gmail.com
Sat Jan 9 07:02:59 EST 2010

On Fri, Jan 8, 2010 at 9:37 PM, DeNigris Sean <sean at clipperadams.com> wrote:

> Hi list,
> I'm writing an example for a class that represents the "pickaxe" e-book,
> which I view in Preview.app:
> describe PickaxeBook do
> ...
>        it "should tell whether it's ready to read" do
>                preview = stub('preview')
>                preview.stub!(:******this is what I'm not sure about - see
> below*******).returns("programming_ruby_1.9.pdf")
>                my_pickaxe_book = PickaxeBook.new(preview)
>                my_pickaxe_book.should be_ready_to_read
>        end
> end
> class PickaxeBook
> ...
>        def ready_to_read?
>                #****** this is the dependency I want to stub:
> preview.front_window.title ********
>                preview.front_window.title =~ /programming_ruby_1.9\.pdf.*/
>        end
> end
> Can you see the problem?  ready_to_read wants to query the object returned
> by front_window, but how do I stub that?  I should note that the Preview
> class is in a different library, which is why I don't just change
> front_window.title
> I thought of a few things, like introducing a role (something like
> "PreviewInfoRetriever") with a method "front_window_title" that forwards to
> preview.front_window.title, but that seems like a lot of complexity.
> To summarize: what's the best way to handle a dependency like
> object.method.method?

There is no universally best way. Stubbing it is fairly straightforward:

  window = stub('window', :title => "programming_ruby_1.9.pdf")
  preview = stub('preview', :front_window => window)

The risk is that this example is now bound to the internal structure of an
object provided by a 3rd party, which can change in a future release. If
that happened, this example might continue passing with a false positive,
and the app won't work.

If you have good high level specs with something like Cucumber or FitNesse,
this risk is diminished. You'll still have to change the example when the
internal structure of Preview changes, but you're less likely to get burned
by deploying code that passes its tests but doesn't work.

If it's easy and inexpensive to create a real instance of Preview, I'd
sooner do that.


> Thanks!
> Sean DeNigris
> sean at clipperadams.com
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20100109/5e5473e5/attachment.html>

More information about the rspec-users mailing list