123456789_123456789_123456789_123456789_123456789_

Module: RSpec::Mocks::MessageExpectation::ImplementationDetails Private

Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Included In:
Defined in: rspec-mocks/lib/rspec/mocks/message_expectation.rb

Overview

Contains the parts of ::RSpec::Mocks::MessageExpectation that aren’t part of rspec-mocks’ public API. The class is very big and could really use some collaborators it delegates to for this stuff but for now this was the simplest way to split the public from private stuff to make it easier to publish the docs for the APIs we want published.

Other Constraints

Instance Attribute Details

#actual_received_count_matters?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 588

def actual_received_count_matters?
  @at_least || @at_most || @exactly
end

#argument_list_matcher=(value) (writeonly)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 413

attr_writer :expected_received_count, :expected_from, :argument_list_matcher

#called_max_times?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 487

def called_max_times?
  @expected_received_count != :any &&
    !@at_least &&
    @expected_received_count > 0 &&
    @actual_received_count >= @expected_received_count
end

#error_generator (rw)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 410

attr_accessor :error_generator, :implementation

#expected_from=(value) (writeonly, protected)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 413

attr_writer :expected_received_count, :expected_from, :argument_list_matcher

#expected_messages_received?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 503

def expected_messages_received?
  ignoring_args? || matches_exact_count? || matches_at_least_count? || matches_at_most_count?
end

#expected_received_count=(value) (writeonly, protected)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 413

attr_writer :expected_received_count, :expected_from, :argument_list_matcher

#has_been_invoked?Boolean (readonly, private)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 632

def has_been_invoked?
  @actual_received_count > 0
end

#ignoring_args?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 512

def ignoring_args?
  @expected_received_count == :any
end

#implementation (rw)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 410

attr_accessor :error_generator, :implementation

#initial_implementation_action=(action) (writeonly, private)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 655

def initial_implementation_action=(action)
  implementation.initial_action = action
end

#inner_implementation_action=(action) (writeonly, private)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 659

def inner_implementation_action=(action)
  return unless action
  warn_about_stub_override if implementation.inner_action
  implementation.inner_action = action
end

#matches_at_least_count?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 516

def matches_at_least_count?
  @at_least && @actual_received_count >= @expected_received_count
end

#matches_at_most_count?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 520

def matches_at_most_count?
  @at_most && @actual_received_count <= @expected_received_count
end

#matches_exact_count?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 524

def matches_exact_count?
  @expected_received_count == @actual_received_count
end

#message (readonly)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 411

attr_reader :message

#negative?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 483

def negative?
  @expected_received_count == 0 && !@at_least
end

#ordered?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 580

def ordered?
  @ordered
end

#orig_object (readonly)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 412

attr_reader :orig_object

#terminal_implementation_action=(action) (writeonly, private)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 665

def terminal_implementation_action=(action)
  implementation.terminal_action = action
end

#type (readonly)

This method is for internal use only.
[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 417

attr_reader :type

#yield_receiver_to_implementation_block?Boolean (readonly)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 459

def yield_receiver_to_implementation_block?
  @yield_receiver_to_implementation_block
end

Instance Method Details

#additional_expected_calls

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 575

def additional_expected_calls
  return 0 if @expectation_type == :stub || !@exactly
  @expected_received_count - 1
end

#advise(*args)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 532

def advise(*args)
  similar_messages << args
end

#and_yield_receiver_to_implementation

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 454

def and_yield_receiver_to_implementation
  @yield_receiver_to_implementation_block = true
  self
end

#description_for(verb)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 564

def description_for(verb)
  @error_generator.describe_expectation(
    verb, @message, @expected_received_count,
    @actual_received_count, expected_args
  )
end

#ensure_expected_ordering_received!

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 507

def ensure_expected_ordering_received!
  @order_group.verify_invocation_order(self) if @ordered
  true
end

#exception_source_id (private)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 600

def exception_source_id
  @exception_source_id ||= "#{self.class.name} #{__id__}"
end

#expectation_count_type

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 558

def expectation_count_type
  return :at_least if @at_least
  return :at_most if @at_most
  nil
end

#expected_args

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 450

def expected_args
  @argument_list_matcher.expected_args
end

#generate_error

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 540

def generate_error
  if similar_messages.empty?
    @error_generator.raise_expectation_error(
      @message, @expected_received_count, @argument_list_matcher,
      @actual_received_count, expectation_count_type, expected_args,
      @expected_from, exception_source_id
    )
  else
    @error_generator.raise_similar_message_args_error(
      self, @similar_messages, @expected_from
    )
  end
end

#increase_actual_received_count!

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 592

def increase_actual_received_count!
  @actual_received_count_write_mutex.synchronize do
    @actual_received_count += 1
  end
end

#initialize(error_generator, expectation_ordering, expected_from, method_double, type = :expectation, opts = {}, &implementation_block)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 420

def initialize(error_generator, expectation_ordering, expected_from, method_double,
               type=:expectation, opts={}, &implementation_block)
  @type = type
  @error_generator = error_generator
  @error_generator.opts = error_generator.opts.merge(opts)
  @expected_from = expected_from
  @method_double = method_double
  @orig_object = @method_double.object
  @message = @method_double.method_name
  @actual_received_count = 0
  @actual_received_count_write_mutex = Support::Mutex.new
  @expected_received_count = type == :expectation ? 1 : :any
  @argument_list_matcher = ArgumentListMatcher::MATCH_ALL
  @order_group = expectation_ordering
  @order_group.register(self) unless type == :stub
  @expectation_type = type
  @ordered = false
  @at_least = @at_most = @exactly = nil

  # Initialized to nil so that we don't allocate an array for every
  # mock or stub. See also comment in `and_yield`.
  @args_to_yield = nil
  @eval_context = nil
  @yield_receiver_to_implementation_block = false

  @implementation = Implementation.new
  self.inner_implementation_action = implementation_block
end

#invoke(parent_stub, *args, &block)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 473

def invoke(parent_stub, *args, &block)
  invoke_incrementing_actual_calls_by(1, true, parent_stub, *args, &block)
end

#invoke_incrementing_actual_calls_by(increment, allowed_to_fail, parent_stub, *args, &block) (private)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 604

def invoke_incrementing_actual_calls_by(increment, allowed_to_fail, parent_stub, *args, &block)
  args.unshift(orig_object) if yield_receiver_to_implementation_block?

  if negative? || (allowed_to_fail && (@exactly || @at_most) && (@actual_received_count == @expected_received_count))
    # args are the args we actually received, @argument_list_matcher is the
    # list of args we were expecting
    @error_generator.raise_expectation_error(
      @message, @expected_received_count,
      @argument_list_matcher,
      @actual_received_count + increment,
      expectation_count_type, args, nil, exception_source_id
    )
  end

  @order_group.handle_order_constraint self

  if implementation.present?
    implementation.call(*args, &block)
  elsif parent_stub
    parent_stub.invoke(nil, *args, &block)
  end
ensure
  @actual_received_count_write_mutex.synchronize do
    @actual_received_count += increment
  end
end

#invoke_without_incrementing_received_count(parent_stub, *args, &block)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 478

def invoke_without_incrementing_received_count(parent_stub, *args, &block)
  invoke_incrementing_actual_calls_by(0, true, parent_stub, *args, &block)
end

#matches?(message, *args) ⇒ Boolean

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 463

def matches?(message, *args)
  @message == message && @argument_list_matcher.args_match?(*args)
end

#matches_name_but_not_args(message, *args)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 494

def matches_name_but_not_args(message, *args)
  @message == message && !@argument_list_matcher.args_match?(*args)
end

#negative_expectation_for?(message) ⇒ Boolean

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 584

def negative_expectation_for?(message)
  @message == message && negative?
end

#raise_already_invoked_error_if_necessary(calling_customization) (private)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 636

def raise_already_invoked_error_if_necessary(calling_customization)
  return unless has_been_invoked?

  error_generator.raise_already_invoked_error(message, calling_customization)
end

#raise_out_of_order_error

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 571

def raise_out_of_order_error
  @error_generator.raise_out_of_order_error @message
end

#raise_unexpected_message_args_error(args_for_multiple_calls)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 554

def raise_unexpected_message_args_error(args_for_multiple_calls)
  @error_generator.raise_unexpected_message_args_error(self, args_for_multiple_calls, exception_source_id)
end

#safe_invoke(parent_stub, *args, &block)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 468

def safe_invoke(parent_stub, *args, &block)
  invoke_incrementing_actual_calls_by(1, false, parent_stub, *args, &block)
end

#set_expected_received_count(relativity, n) (private)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 642

def set_expected_received_count(relativity, n)
  raise "`count` is not supported with negative message expectations" if negative?
  @at_least = (relativity == :at_least)
  @at_most  = (relativity == :at_most)
  @exactly  = (relativity == :exactly)
  @expected_received_count = case n
                             when Numeric then n
                             when :once   then 1
                             when :twice  then 2
                             when :thrice then 3
                             end
end

#similar_messages

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 528

def similar_messages
  @similar_messages ||= []
end

#unadvise(args)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 536

def unadvise(args)
  similar_messages.delete_if { |message| args.include?(message) }
end

#verify_messages_received

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 498

def verify_messages_received
  return if expected_messages_received?
  generate_error
end

#warn_about_stub_override (private)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 669

def warn_about_stub_override
  RSpec.warning(
    "You're overriding a previous stub implementation of `#{@message}`. " \
    "Called from #{CallerFilter.first_non_rspec_line}."
  )
end

#wrap_original(method_name, &block) (private)

[ GitHub ]

  
# File 'rspec-mocks/lib/rspec/mocks/message_expectation.rb', line 676

def wrap_original(method_name, &block)
  if RSpec::Mocks::TestDouble === @method_double.object
    @error_generator.raise_only_valid_on_a_partial_double(method_name)
  else
    warn_about_stub_override if implementation.inner_action
    @implementation = AndWrapOriginalImplementation.new(@method_double.original_implementation_callable, block)
    @yield_receiver_to_implementation_block = false
  end

  nil
end