Posted almost 7 years ago. Visible to the public.

RSpec: Stubbing a method that takes a block

If you stub a method or set expectations with should_receive these stubbed methods may also yield blocks. This is handy if the returning object is receiving a block call.

Consider this, where you cannot say and_return [] because of the block:

Copy
def crawl_messages Message.find_in_batches do |messages| messages.each(&:crawl) end end

It works similar to and_return – just use and_yield:

Copy
describe '#crawl_messages' do it 'should process messages in batches so the server stays alive' do message = stub message.should_receive(:crawl) Message.should_receive(:find_in_batches).and_yield([message]) subject.crawl_messages end end

You can also combine and_yield with and_return. Mind the order:

Copy
item = stub('a block') subject.should_receive(:something).and_yield(item).and_return 'result'

Yielding multiple times

You can even chain multiple and_yield statements to yield the block multiple times with different arguments:

Copy
subject.should_receive(:something).and_yield(item1).and_yield(item2)

By refactoring problematic code and creating automated tests, makandra can vastly improve the maintainability of your Rails application.

Author of this card:

Avatar
Arne Hartherz
Last edit:
12 months ago
by Arne Hartherz
Keywords:
call, invocation, returning, return
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Arne Hartherz to makandra dev