rspec / rspec-mocks

RSpec's 'test double' framework, with support for stubbing and mocking
https://rspec.info
MIT License
1.16k stars 358 forks source link

Extend and_invoke docs #1585

Closed pirj closed 2 months ago

pirj commented 3 months ago

There's no other way certain things can be done.

It came handy the other day when I needed to add a spec for something that runs in a loop, to end the loop conditionally. It's helpful to mix raising exceptions with yielding, too.

  class Sut
    def main_loop
      until requested_stop?
        abc.foo { |bar| puts bar }
      end
    end
  end

  class Abc
    # ...
    def foo(&_block)
      bar = baz.baz
      yield bar
    end
  end
# spec
    abc = Abc.new
    main_loop = Sut.new(abc)
    allow(abc).to receive(:foo)
                             .and_invoke(
                               proc { |&block|
                                 main_loop.stop!
                                 block.call("bar") # NOTE: yield isn't available here
                               }
                             )

    main_loop.run