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

Ben Mabey ben at benmabey.com
Sat Feb 28 21:19:24 EST 2009


Shot (Piotr Szotkowski) wrote:
> I’m trying to spec a system from outside-in as an excercise in ‘emergent 
> design’ – and so far I love it; it made me think about the design for 
> two days before I even wrote the first spec… :)
>
> My most-outside class seems to be a prime candidate for an #each method. 
> The attached (stripped) spec carrying two of the approaches I came up 
> with passes, and raises the following quesitions – any answer would be 
> most appreciated!
>
> 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?
>
> 2. The first spec shows my initial approach, with a variable polling the 
> stuff yielded by #each and then validating its contents, but it seems 
> clumsy…
>
> 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)?
>
> 4. Is there any better or more elegant 
> way to spec an #each (or #next) method?
>   

Hmm.. maybe this is what you are looking for (From 
http://rspec.info/documentation/mocks/message_expectations.html):

Yielding

my_mock.should_receive(:msg).once.and_yield(<value-1>, <value-2>, ..., 
<value-n>)
When the expected message is received, the mock will yield the values to 
the passed block.

To mock a method which yields values multiple times, and_yield can be 
chained.

my_mock.should_receive(:msg).once.and_yield(<value-0-1>, <value-0-2>, 
..., <value-0-n>).
and_yield(<value-1-1>, <value-1-2>, ..., <value-1-n>).
and_yield(<value-2-1>, <value-2-2>, ..., <value-2-n>)


HTH,
Ben


More information about the rspec-users mailing list