class RSpec::Mocks::MessageExpectation

Represents an individual method stub or message expectation. The methods defined here can be used to configure how it behaves. The methods return `self` so that they can be chained together to form a fluent interface.

Public Instance Methods

and_call_original() click to toggle source

Tells the object to delegate to the original unmodified method when it receives the message.

@note This is only available on partial doubles.

@return [nil] No further chaining is supported after this. @example

expect(counter).to receive(:increment).and_call_original
original_count = counter.count
counter.increment
expect(counter.count).to eq(original_count + 1)
# File lib/rspec/mocks/message_expectation.rb, line 97
def and_call_original
  wrap_original(__method__) do |original, *args, &block|
    original.call(*args, &block)
  end
end
and_raise(*args) click to toggle source

@overload #and_raise @overload #and_raise(ExceptionClass) @overload #and_raise(ExceptionClass, message) @overload #and_raise(exception_instance)

Tells the object to raise an exception when the message is received.

@return [nil] No further chaining is supported after this. @note

When you pass an exception class, the MessageExpectation will raise
an instance of it, creating it with `exception` and passing `message`
if specified.  If the exception class initializer requires more than
one parameters, you must pass in an instance and not the class,
otherwise this method will raise an ArgumentError exception.

@example

allow(car).to receive(:go).and_raise
allow(car).to receive(:go).and_raise(OutOfGas)
allow(car).to receive(:go).and_raise(OutOfGas, "At least 2 oz of gas needed to drive")
allow(car).to receive(:go).and_raise(OutOfGas.new(2, :oz))
# File lib/rspec/mocks/message_expectation.rb, line 139
def and_raise(*args)
  raise_already_invoked_error_if_necessary(__method__)
  self.terminal_implementation_action = Proc.new { raise(*args) }
  nil
end
and_return(first_value, *values) click to toggle source

@overload #and_return(value) @overload #and_return(first_value, second_value)

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

If the message is received more times than there are values, the last value is received for every subsequent call.

@return [nil] No further chaining is supported after this. @example

allow(counter).to receive(:count).and_return(1)
counter.count # => 1
counter.count # => 1

allow(counter).to receive(:count).and_return(1,2,3)
counter.count # => 1
counter.count # => 2
counter.count # => 3
counter.count # => 3
counter.count # => 3
# etc
# File lib/rspec/mocks/message_expectation.rb, line 69
def and_return(first_value, *values)
  raise_already_invoked_error_if_necessary(__method__)
  if negative?
    raise "`and_return` is not supported with negative message expectations"
  end

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

  values.unshift(first_value)
  @expected_received_count = [@expected_received_count, values.size].max unless ignoring_args? || (@expected_received_count == 0 && @at_least)
  self.terminal_implementation_action = AndReturnImplementation.new(values)

  nil
end
and_throw(*args) click to toggle source

@overload #and_throw(symbol) @overload #and_throw(symbol, object)

Tells the object to throw a symbol (with the object if that form is used) when the message is received.

@return [nil] No further chaining is supported after this. @example

allow(car).to receive(:go).and_throw(:out_of_gas)
allow(car).to receive(:go).and_throw(:out_of_gas, :level => 0.1)
# File lib/rspec/mocks/message_expectation.rb, line 155
def and_throw(*args)
  raise_already_invoked_error_if_necessary(__method__)
  self.terminal_implementation_action = Proc.new { throw(*args) }
  nil
end
and_wrap_original(&block) click to toggle source

Decorates the stubbed method with the supplied block. The original unmodified method is passed to the block along with any method call arguments so you can delegate to it, whilst still being able to change what args are passed to it and/or change the return value.

@note This is only available on partial doubles.

@return [nil] No further chaining is supported after this. @example

expect(api).to receive(:large_list).and_wrap_original do |original_method, *args, &block|
  original_method.call(*args, &block).first(10)
end
# File lib/rspec/mocks/message_expectation.rb, line 115
def and_wrap_original(&block)
  wrap_original(__method__, &block)
end
and_yield(*args) { |eval_context = object| ... } click to toggle source

Tells the object to yield one or more args to a block when the message is received.

@return [MessageExpectation] self, to support further chaining. @example

stream.stub(:open).and_yield(StringIO.new)
# File lib/rspec/mocks/message_expectation.rb, line 167
def and_yield(*args, &block)
  raise_already_invoked_error_if_necessary(__method__)
  yield @eval_context = Object.new if block

  # Initialize args to yield now that it's being used, see also: comment
  # in constructor.
  @args_to_yield ||= []

  @args_to_yield << args
  self.initial_implementation_action = AndYieldImplementation.new(@args_to_yield, @eval_context, @error_generator)
  self
end
at_least(n, &block) click to toggle source

Constrain a message expectation to be received at least a specific number of times.

@return [MessageExpectation] self, to support further chaining. @example

expect(dealer).to receive(:deal_card).at_least(9).times
# File lib/rspec/mocks/message_expectation.rb, line 202
def at_least(n, &block)
  raise_already_invoked_error_if_necessary(__method__)
  set_expected_received_count :at_least, n

  if n == 0
    raise "at_least(0) has been removed, use allow(...).to receive(:message) instead"
  end

  self.inner_implementation_action = block

  self
end
at_most(n, &block) click to toggle source

Constrain a message expectation to be received at most a specific number of times.

@return [MessageExpectation] self, to support further chaining. @example

expect(dealer).to receive(:deal_card).at_most(10).times
# File lib/rspec/mocks/message_expectation.rb, line 221
def at_most(n, &block)
  raise_already_invoked_error_if_necessary(__method__)
  self.inner_implementation_action = block
  set_expected_received_count :at_most, n
  self
end
exactly(n, &block) click to toggle source

Constrain a message expectation to be received a specific number of times.

@return [MessageExpectation] self, to support further chaining. @example

expect(dealer).to receive(:deal_card).exactly(10).times
# File lib/rspec/mocks/message_expectation.rb, line 189
def exactly(n, &block)
  raise_already_invoked_error_if_necessary(__method__)
  self.inner_implementation_action = block
  set_expected_received_count :exactly, n
  self
end
inspect()
Alias for: to_s
never() click to toggle source

Expect a message not to be received at all.

@return [MessageExpectation] self, to support further chaining. @example

expect(car).to receive(:stop).never
# File lib/rspec/mocks/message_expectation.rb, line 245
def never
  error_generator.raise_double_negation_error("expect(obj)") if negative?
  @expected_received_count = 0
  self
end
once(&block) click to toggle source

Expect a message to be received exactly one time.

@return [MessageExpectation] self, to support further chaining. @example

expect(car).to receive(:go).once
# File lib/rspec/mocks/message_expectation.rb, line 256
def once(&block)
  self.inner_implementation_action = block
  set_expected_received_count :exactly, 1
  self
end
ordered(&block) click to toggle source

Expect messages to be received in a specific order.

@return [MessageExpectation] self, to support further chaining. @example

expect(api).to receive(:prepare).ordered
expect(api).to receive(:run).ordered
expect(api).to receive(:finish).ordered
# File lib/rspec/mocks/message_expectation.rb, line 330
def ordered(&block)
  if type == :stub
    RSpec.warning(
      "`allow(...).to receive(..).ordered` is not supported and will"              "have no effect, use `and_return(*ordered_values)` instead."
    )
  end

  self.inner_implementation_action = block
  additional_expected_calls.times do
    @order_group.register(self)
  end
  @ordered = true
  self
end
thrice(&block) click to toggle source

Expect a message to be received exactly three times.

@return [MessageExpectation] self, to support further chaining. @example

expect(car).to receive(:go).thrice
# File lib/rspec/mocks/message_expectation.rb, line 278
def thrice(&block)
  self.inner_implementation_action = block
  set_expected_received_count :exactly, 3
  self
end
times(&block) click to toggle source

Syntactic sugar for `exactly`, `at_least` and `at_most`

@return [MessageExpectation] self, to support further chaining. @example

expect(dealer).to receive(:deal_card).exactly(10).times
expect(dealer).to receive(:deal_card).at_least(10).times
expect(dealer).to receive(:deal_card).at_most(10).times
# File lib/rspec/mocks/message_expectation.rb, line 235
def times(&block)
  self.inner_implementation_action = block
  self
end
to_s() click to toggle source

@return [String] a nice representation of the message expectation

# File lib/rspec/mocks/message_expectation.rb, line 347
def to_s
  args_description = error_generator.method_call_args_description(@argument_list_matcher.expected_args, "", "") { true }
  args_description = "(#{args_description})" unless args_description.start_with?("(")
  "#<#{self.class} #{error_generator.intro}.#{message}#{args_description}>"
end
Also aliased as: inspect
twice(&block) click to toggle source

Expect a message to be received exactly two times.

@return [MessageExpectation] self, to support further chaining. @example

expect(car).to receive(:go).twice
# File lib/rspec/mocks/message_expectation.rb, line 267
def twice(&block)
  self.inner_implementation_action = block
  set_expected_received_count :exactly, 2
  self
end
with(*args, &block) click to toggle source

Constrains a stub or message expectation to invocations with specific arguments.

With a stub, if the message might be received with other args as well, you should stub a default value first, and then stub or mock the same message using `with` to constrain to specific arguments.

A message expectation will fail if the message is received with different arguments.

@return [MessageExpectation] self, to support further chaining. @example

allow(cart).to receive(:add) { :failure }
allow(cart).to receive(:add).with(Book.new(:isbn => 1934356379)) { :success }
cart.add(Book.new(:isbn => 1234567890))
# => :failure
cart.add(Book.new(:isbn => 1934356379))
# => :success

expect(cart).to receive(:add).with(Book.new(:isbn => 1934356379)) { :success }
cart.add(Book.new(:isbn => 1234567890))
# => failed expectation
cart.add(Book.new(:isbn => 1934356379))
# => passes
# File lib/rspec/mocks/message_expectation.rb, line 311
def with(*args, &block)
  raise_already_invoked_error_if_necessary(__method__)
  if args.empty?
    raise ArgumentError,
          "`with` must have at least one argument. Use `no_args` matcher to set the expectation of receiving no arguments."
  end

  self.inner_implementation_action = block
  @argument_list_matcher = ArgumentListMatcher.new(*args)
  self
end