Alex's Slip-box

These are my org-mode notes in sort of Zettelkasten style

RSpec and blocks

: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

Search Results