module RSpec::Mocks::MessageExpectation::ImplementationDetails
def actual_received_count_matters?
def actual_received_count_matters? @at_least || @at_most || @exactly end
def additional_expected_calls
def additional_expected_calls return 0 if @expectation_type == :stub || !@exactly @expected_received_count - 1 end
def advise(*args)
def advise(*args) similar_messages << args end
def and_yield_receiver_to_implementation
def and_yield_receiver_to_implementation @yield_receiver_to_implementation_block = true self end
def called_max_times?
def called_max_times? @expected_received_count != :any && !@at_least && @expected_received_count > 0 && @actual_received_count >= @expected_received_count end
def description_for(verb)
def description_for(verb) @error_generator.describe_expectation( verb, @message, @expected_received_count, @actual_received_count, expected_args ) end
def ensure_expected_ordering_received!
def ensure_expected_ordering_received! @order_group.verify_invocation_order(self) if @ordered true end
def exception_source_id
def exception_source_id @exception_source_id ||= "#{self.class.name} #{__id__}" end
def expectation_count_type
def expectation_count_type return :at_least if @at_least return :at_most if @at_most nil end
def expected_args
def expected_args @argument_list_matcher.expected_args end
def expected_messages_received?
def expected_messages_received? ignoring_args? || matches_exact_count? || matches_at_least_count? || matches_at_most_count? end
def generate_error
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
def has_been_invoked?
def has_been_invoked? @actual_received_count > 0 end
def ignoring_args?
def ignoring_args? @expected_received_count == :any end
def increase_actual_received_count!
def increase_actual_received_count! @actual_received_count_write_mutex.synchronize do @actual_received_count += 1 end end
def initial_implementation_action=(action)
def initial_implementation_action=(action) implementation.initial_action = action end
def initialize(error_generator, expectation_ordering, expected_from, method_double,
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
def inner_implementation_action=(action)
def inner_implementation_action=(action) return unless action warn_about_stub_override if implementation.inner_action implementation.inner_action = action end
def invoke(parent_stub, *args, &block)
def invoke(parent_stub, *args, &block) invoke_incrementing_actual_calls_by(1, true, parent_stub, *args, &block) end
def invoke_incrementing_actual_calls_by(increment, allowed_to_fail, parent_stub, *args, &block)
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
def invoke_without_incrementing_received_count(parent_stub, *args, &block)
def invoke_without_incrementing_received_count(parent_stub, *args, &block) invoke_incrementing_actual_calls_by(0, true, parent_stub, *args, &block) end
def matches?(message, *args)
def matches?(message, *args) @message == message && @argument_list_matcher.args_match?(*args) end
def matches_at_least_count?
def matches_at_least_count? @at_least && @actual_received_count >= @expected_received_count end
def matches_at_most_count?
def matches_at_most_count? @at_most && @actual_received_count <= @expected_received_count end
def matches_exact_count?
def matches_exact_count? @expected_received_count == @actual_received_count end
def matches_name_but_not_args(message, *args)
def matches_name_but_not_args(message, *args) @message == message && !@argument_list_matcher.args_match?(*args) end
def negative?
def negative? @expected_received_count == 0 && !@at_least end
def negative_expectation_for?(message)
def negative_expectation_for?(message) @message == message && negative? end
def ordered?
def ordered? @ordered end
def raise_already_invoked_error_if_necessary(calling_customization)
def raise_already_invoked_error_if_necessary(calling_customization) return unless has_been_invoked? error_generator.raise_already_invoked_error(message, calling_customization) end
def raise_out_of_order_error
def raise_out_of_order_error @error_generator.raise_out_of_order_error @message end
def raise_unexpected_message_args_error(args_for_multiple_calls)
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
def safe_invoke(parent_stub, *args, &block)
def safe_invoke(parent_stub, *args, &block) invoke_incrementing_actual_calls_by(1, false, parent_stub, *args, &block) end
def set_expected_received_count(relativity, n)
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
def similar_messages
def similar_messages @similar_messages ||= [] end
def terminal_implementation_action=(action)
def terminal_implementation_action=(action) implementation.terminal_action = action end
def unadvise(args)
def unadvise(args) similar_messages.delete_if { |message| args.include?(message) } end
def verify_messages_received
def verify_messages_received return if expected_messages_received? generate_error end
def warn_about_stub_override
def warn_about_stub_override RSpec.warning( "You're overriding a previous stub implementation of `#{@message}`. " \ "Called from #{CallerFilter.first_non_rspec_line}." ) end
def wrap_original(method_name, &block)
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
def yield_receiver_to_implementation_block?
def yield_receiver_to_implementation_block? @yield_receiver_to_implementation_block end