RSpec and blocks
Table of Contents
:ID: E559724D-A7A8-438E-8042-1018DFA34AE3
How to test this with RSpec?
module Thing def self.call Foo.call do Bar.call end yield end end
# Stubbing
When stubbing Foo.call
, in order for block that contains Bar.call
to be
called, we need to use and_yield
. It can take arguments. See also
https://www.rubydoc.info/gems/rspec-mocks/RSpec%2FMocks%2FMessageExpectation:and_yield
RSpec.describe Thing do before do allow(Foo).to receive(:call).and_yield allow(Bar).to receive(:call) end describe '.call' do it 'calls Foo' do described_class.call expect(Foo).to have_received(:call) end it 'calls Bar' do described_class.call expect(Bar).to have_received(:call) end end end
# Expecting
We can expect the subject under test to yield control by passing a block to
expect with an argument. The argument itself is a block, captured (&b
) and
passed to the method call. See also https://relishapp.com/rspec/rspec-expectations/v/3-11/docs/built-in-matchers/yield-matchers
it 'yields control to a block' do expect do |b| described_class.call(&b) end.to yield_control end
# Other RSpecy things
This isn’t related to block testing, but putting this here for now.
# and_invoke
Can be used to stub multiple calls to the same method, which could raise and retry see also https://www.rubydoc.info/github/rspec/rspec-mocks/RSpec%2FMocks%2FMessageExpectation:and_invoke