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

Shot (Piotr Szotkowski) shot at hot.pl
Sun Mar 1 12:30:06 EST 2009

Thanks a lot, Matt, for your reply! It’s seriously most enlightening.

Matt Wynne:

> On 28 Feb 2009, at 21:29, Shot (Piotr Szotkowski) wrote:

>> 1. A philosophical/kosherness question: In the finished system
>> Decomposer#each will yield Decomposition objects, but as I’m specing
>> from outside-in, the Decomposition class is not yet created. In the
>> attached example I’m using an Array as a poor man’s Decomposition
>> replacement. Is this a sane approach, or should I rather create
>> a skeletal Decomposition#initialize instead?

> I think you should try to write the specs so they won't have to change 
> when you build the real implementation. That doesn't mean creating an 
> actual Decomposition class just yet, but it does mean that you should 
> return something that looks enough like one for the tests to still be 
> valid when you swap one in.

Hmm, interesting – so an outside-in implementation should side-step 
using future classes’ constructors, and the implementation code should 
actually change when the relevant classes appear?

I ended up creating a skeletal Decomposition class, but then had to 
add Decomposition#==(other) – which, in turn, made me add attribute 
accessors – just to be able to test against Decomposition objects in 

Decomposition#== will be useful in the future, but currently it exists 
solely so I can use RSpec’s ….should == Decomposition.new(…), which 
seems wrong. Hmm, another thing to ponder upon – every time a new RSpec 
paradigm shows me something new, some other, unrelated spec begins to 
raise suspicions… :)

> I think what you're finding clumsy here is the mocking setup. You 
> don't always have to use mock objects as your 'test doubles' and often 
> it's much easier (and leaves behind more flexible tests) if you use 
> stubs rather than mocks.

Thanks a ton for the Array-based generators – I haven’t thought of that; 
they are most interesting. I can’t use your example verbatim, as in my 
real code Decomposer.new takes class names and only then instantiates 
the relevant generators¹, but it surely opened my eyes on stubbing 
objects with general-purpose classes rather than mocking them. I’ll 
see how I can use them to clean-up the specs. :)

¹ http://github.com/Chastell/art-decomp/commit/f9f8d3b2a3e431290d0656f7244b64f5376fab8f

>> 3. …so I came up with the second, Decomposer.new.to_enum approach, 
>> which simply validates the enumrator’s #next objects. Unfortunately, 
>> this does not seem to trigger #should_receive(:each) on the *_gen 
>> mocks and made me #stub!(:each) on them instead. Is this because
>> I’m using RSpec 1.1.12 with Ruby 1.9.1, or am I missing something
>> on how message expectations work with lazy iterators (and, thus, 
>> #should_receive fail properly)?

> I think you're getting too far into specifying the
> implementation here. I like the #each approach better.

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?

For reference, my original attachment: http://gist.github.com/72399 – 
if you replace the #stub!()s in the second spec with #should_receive()s, 
the spec breaks with (allegedly) unsatisfied expectations.

— 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/20090301/b8481eb4/attachment.bin>

More information about the rspec-users mailing list