class RSpec::Mocks::MethodDouble

@private

Attributes

method_name[R]

@private

object[R]

@private

Public Class Methods

new(object, method_name, proxy) click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 9
def initialize(object, method_name, proxy)
  @method_name = method_name
  @object = object
  @proxy = proxy

  @method_stasher = InstanceMethodStasher.new(object_singleton_class, @method_name)
  @method_is_proxied = false
  store(:expectations, [])
  store(:stubs, [])
end

Public Instance Methods

add_default_stub(*args, &implementation) click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 233
def add_default_stub(*args, &implementation)
  return if stubs.any?
  add_stub(*args, &implementation)
end
add_expectation(error_generator, expectation_ordering, expected_from, opts, &implementation) click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 206
def add_expectation(error_generator, expectation_ordering, expected_from, opts, &implementation)
  configure_method
  expectation = MessageExpectation.new(error_generator, expectation_ordering,
                                       expected_from, self, 1, opts, &implementation)
  expectations << expectation
  expectation
end
add_negative_expectation(error_generator, expectation_ordering, expected_from, &implementation) click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 215
def add_negative_expectation(error_generator, expectation_ordering, expected_from, &implementation)
  configure_method
  expectation = NegativeMessageExpectation.new(error_generator, expectation_ordering,
                                               expected_from, self, &implementation)
  expectations.unshift expectation
  expectation
end
add_stub(error_generator, expectation_ordering, expected_from, opts={}, &implementation) click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 224
def add_stub(error_generator, expectation_ordering, expected_from, opts={}, &implementation)
  configure_method
  stub = MessageExpectation.new(error_generator, expectation_ordering, expected_from,
                                self, :any, opts, &implementation)
  stubs.unshift stub
  stub
end
any_instance_class_recorder_observing_method?(klass) click to toggle source
# File lib/rspec/mocks/method_double.rb, line 93
def any_instance_class_recorder_observing_method?(klass)
  return true if klass.__recorder.already_observing?(@method_name)
  superklass = klass.superclass
  return false if superklass.nil?
  any_instance_class_recorder_observing_method?(superklass)
end
clear() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 200
def clear
  expectations.clear
  stubs.clear
end
configure_method() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 144
def configure_method
  RSpec::Mocks::space.add(@object) if RSpec::Mocks::space
  warn_if_nil_class
  @original_visibility = visibility_for_method
  @method_stasher.stash unless @method_is_proxied
  define_proxy_method
end
define_proxy_method() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 153
      def define_proxy_method
        return if @method_is_proxied

        object_singleton_class.class_eval "          def #{@method_name}(*args, &block)
            __mock_proxy.message_received :#{@method_name}, *args, &block
          end
          #{visibility_for_method}
", __FILE__, __LINE__ + 1
        @method_is_proxied = true
      end
expectations() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 21
def expectations
  self[:expectations]
end
object_singleton_class() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 139
def object_singleton_class
  class << @object; self; end
end
original_method() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 44
def original_method
  if @method_stasher.method_is_stashed?
    # Example: a singleton method defined on @object
    ::RSpec::Mocks.method_handle_for(@object, @method_stasher.stashed_method_name)
  elsif meth = original_unrecorded_any_instance_method
    # Example: a method that has been mocked through
    #   klass.any_instance.should_receive(:msg).and_call_original
    # any_instance.should_receive(:msg) causes the method to be
    # replaced with a proxy method, and then `and_call_original`
    # is recorded and played back on the object instance. We need
    # special handling here to get a handle on the original method
    # object rather than the proxy method.
    meth
  else
    begin
      # Example: an instance method defined on one of @object's ancestors.
      original_method_from_ancestor(object_singleton_class.ancestors)
    rescue NameError
      raise unless @object.respond_to?(:superclass)

      # Example: a singleton method defined on @object's superclass.
      #
      # Note: we have to give precedence to instance methods
      # defined on @object's class, because in a case like:
      #
      # `klass.should_receive(:new).and_call_original`
      #
      # ...we want `Class#new` bound to `klass` (which will return
      # an instance of `klass`), not `klass.superclass.new` (which
      # would return an instance of `klass.superclass`).
      original_method_from_superclass
    end
  end
rescue NameError
  # We have no way of knowing if the object's method_missing
  # will handle this message or not...but we can at least try.
  # If it's not handled, a `NoMethodError` will be raised, just
  # like normally.
  Proc.new do |*args, &block|
    @object.__send__(:method_missing, @method_name, *args, &block)
  end
end
original_method_from_ancestor(ancestors) click to toggle source
# File lib/rspec/mocks/method_double.rb, line 100
def original_method_from_ancestor(ancestors)
  klass, *rest = ancestors
  klass.instance_method(@method_name).bind(@object)
rescue NameError
  raise if rest.empty?
  original_method_from_ancestor(rest)
end
original_method_from_superclass() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 110
def original_method_from_superclass
  @object.superclass.
          singleton_class.
          instance_method(@method_name).
          bind(@object)
end
original_unrecorded_any_instance_method() click to toggle source
# File lib/rspec/mocks/method_double.rb, line 87
def original_unrecorded_any_instance_method
  return nil unless any_instance_class_recorder_observing_method?(@object.class)
  alias_name = @object.class.__recorder.build_alias_method_name(@method_name)
  @object.method(alias_name)
end
proxy_for_nil_class?() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 245
def proxy_for_nil_class?
  NilClass === @object
end
raise_method_not_stubbed_error() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 257
def raise_method_not_stubbed_error
  raise MockExpectationError, "The method `#{method_name}` was not stubbed or was already unstubbed" 
end
remove_stub() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 239
def remove_stub
  raise_method_not_stubbed_error if stubs.empty?
  expectations.empty? ? reset : stubs.clear
end
reset() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 193
def reset
  reset_nil_expectations_warning
  restore_original_method
  clear
end
reset_nil_expectations_warning() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 262
def reset_nil_expectations_warning
  RSpec::Mocks::Proxy.warn_about_expectations_on_nil = true if proxy_for_nil_class?
end
restore_original_method() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 171
def restore_original_method
  return unless @method_is_proxied

  object_singleton_class.__send__(:remove_method, @method_name)
  @method_stasher.restore
  restore_original_visibility

  @method_is_proxied = false
end
restore_original_visibility() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 182
def restore_original_visibility
  return unless object_singleton_class.method_defined?(@method_name) || object_singleton_class.private_method_defined?(@method_name)
  object_singleton_class.class_eval(@original_visibility, __FILE__, __LINE__)
end
stubs() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 26
def stubs
  self[:stubs]
end
verify() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 188
def verify
  expectations.each {|e| e.verify_messages_received}
end
visibility() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 31
def visibility
  if TestDouble === @object
    'public'
  elsif object_singleton_class.private_method_defined?(@method_name)
    'private'
  elsif object_singleton_class.protected_method_defined?(@method_name)
    'protected'
  else
    'public'
  end
end
visibility_for_method() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 166
def visibility_for_method
  "#{visibility} :#{method_name}"
end
warn_if_nil_class() click to toggle source

@private

# File lib/rspec/mocks/method_double.rb, line 250
def warn_if_nil_class
  if proxy_for_nil_class? & RSpec::Mocks::Proxy.warn_about_expectations_on_nil
    Kernel.warn("An expectation of :#{@method_name} was set on nil. Called from #{caller[4]}. Use allow_message_expectations_on_nil to disable warnings.")
  end
end