Method: RSpec::Mocks::MessageExpectation#and_invoke

Defined in:
lib/rspec/mocks/message_expectation.rb

#and_invoke(first_proc, *procs, &_block) ⇒ nil

Tells the object to invoke a Proc when it receives the message. Given more than one value, the result of the first Proc is returned the first time the message is received, the result of the second Proc is returned the next time, etc, etc.

If the message is received more times than there are Procs, the result of the last Proc is returned for every subsequent call.

Examples:

allow(api).to receive(:get_foo).and_invoke(-> { raise ApiTimeout })
api.get_foo # => raises ApiTimeout
api.get_foo # => raises ApiTimeout

allow(api).to receive(:get_foo).and_invoke(-> { raise ApiTimeout }, -> { raise ApiTimeout }, -> { :a_foo })
api.get_foo # => raises ApiTimeout
api.get_foo # => raises ApiTimeout
api.get_foo # => :a_foo
api.get_foo # => :a_foo
api.get_foo # => :a_foo
# etc

Returns:

  • (nil)

    No further chaining is supported after this.



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/rspec/mocks/message_expectation.rb', line 109

def and_invoke(first_proc, *procs, &_block)
  raise_already_invoked_error_if_necessary(__method__)
  if negative?
    raise "`and_invoke` is not supported with negative message expectations"
  end

  if block_given?
    raise ArgumentError, "Implementation blocks aren't supported with `and_invoke`"
  end

  procs.unshift(first_proc)
  if procs.any? { |p| !p.respond_to?(:call) }
    raise ArgumentError, "Arguments to `and_invoke` must be callable."
  end

  @expected_received_count = [@expected_received_count, procs.size].max unless ignoring_args? || (@expected_received_count == 0 && @at_least)
  self.terminal_implementation_action = AndInvokeImplementation.new(procs)

  nil
end