[rspec-users] Rspecing an enumerator from outside-in woes

Shot (Piotr Szotkowski) shot at hot.pl
Mon Mar 2 18:32:26 EST 2009

Once again – thanks a ton for your response! I wish ‘The RSpec Book’ 
answered my use cases; I bought it hoping I’ll learn all this stuff from 
it, but it seems the most interesting chapters are not written yet. :)

Matt Wynne:

> Assuming you wanted to keep your focus on the Decomposer class, but 
> you knew that the concept of a Decomposition was a firm one in your 
> design, you could define an empty Decomposition class, then stub the 
> constructor to return a test double of some sort:

>     class Decomposition
>     end

>     ...

>     Decomposition.stub!(:new).and_return mock('Decomposition', :foo => 'bar')

Ah, a very good point. :) The idea of subclassing something to make
it testable is also interesting; I’d rather try hard to come up
with a better spec and/or design, but it’s good to remember there’s 
a solution to keep all the code added solely for testability in one 

> Ideally though, you really want to avoid testing state and instead 
> think about testing the interactions between objects. If the 
> relationship between the Decomposer and the Decomposition is for
> one to create instances of the other, then I would be quite satisfied 
> writing mock expectations on the Decomposition's constructor, like 
> this:

>      Decomposition.should_receive(:new).with [1,2]

And this is exactly where you hit the nail on the head. :) I think
my main problem at this stage of ‘getting RSpec’ is the (shrinking, 
but still existing) inability to blur the border between the RSpec world 
and the world of the code under test. I happily started to use mocks and 
stubs, but I keep forgetting that they can be applied to the stuff from 
the ‘other’ world; I hope I’ll keep that in mind from now on.

FWIW, your example on replacing 
with a fake generator struck a very nice chord with
me, and I managed to side-step the problem that all
three of my generator types expect a varying number
of params to their #each calls:

> On 1 Mar 2009, at 17:30, Shot (Piotr Szotkowski) wrote:

>> I think I agree – but the real question was why don’t the (lazy)
>> enumerator’s #next calls satisfy the mocks’ #should_receive()s –
>> am I missing something fundamental, or is this simply an RSpec 1.1.12
>> incompatibility with Ruby 1.9.1?

> Sorry, not sure about that one - I've not tried playing
> with these lazy enumerators - is this a Ruby 1.9 thing

Yes and no – some/all of the Enumerator stuff was backported to 1.8 and 
is included in Ruby 1.8.7. Basically, if you have an #each method on 
your class, you can create an Enumerator¹ for its objects and then do 
very nice things, like having a free #with_index traversal or fetching 
the elements one-by-one with #next. The latter is useful for classes 
generating/representing infinite sequences and in cases (like my case 
of interdependent generators) when the cost of generating subsequent 
elements is rather high and it would be wasteful to generate all of them 

¹ http://ruby-doc.org/core-1.9/classes/Enumerable/Enumerator.html

— Shot
uoıʇɔnɹʇsuoɔ ɹəpun
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090303/5b5e72e2/attachment.bin>

More information about the rspec-users mailing list