class RSpec::Mocks::AnyInstance::Recorder

Given a class ‘TheClass`, `TheClass.any_instance` returns a `Recorder`, which records stubs and message expectations for later playback on instances of `TheClass`.

Further constraints are stored in instances of [Chain](Chain).

@see AnyInstance @see Chain

Attributes

@private

@private

Public Class Methods

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 16
def initialize(klass)
  @message_chains = MessageChains.new
  @stubs = Hash.new { |hash, key| hash[key] = [] }
  @observed_methods = []
  @played_methods = {}
  @backed_up_method_owner = {}
  @klass = klass
  @expectation_set = false

  return unless RSpec::Mocks.configuration.verify_partial_doubles?
  RSpec::Mocks.configuration.verifying_double_callbacks.each do |block|
    block.call(ObjectReference.for(klass))
  end
end

Public Instance Methods

@private

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 127
def already_observing?(method_name)
  @observed_methods.include?(method_name) || super_class_observing?(method_name)
end

@private

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 122
def build_alias_method_name(method_name)
  "__#{method_name}_without_any_instance__"
end

@private

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 53
def expect_chain(*method_names_and_optional_return_values, &block)
  @expectation_set = true
  normalize_chain(*method_names_and_optional_return_values) do |method_name, args|
    observe!(method_name)
    message_chains.add(method_name, ExpectChainChain.new(self, *args, &block))
  end
end

@private

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 117
def instance_that_received(method_name)
  @played_methods[method_name]
end

@private

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 132
def notify_received_message(_object, message, args, _blk)
  has_expectation = false

  message_chains.each_unfulfilled_expectation_matching(message, *args) do |expectation|
    has_expectation = true
    expectation.expectation_fulfilled!
  end

  return unless has_expectation

  restore_method!(message)
  mark_invoked!(message)
end

@private

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 109
def playback!(instance, method_name)
  RSpec::Mocks.space.ensure_registered(instance)
  message_chains.playback!(instance, method_name)
  @played_methods[method_name] = instance
  received_expected_message!(method_name) if message_chains.has_expectation?(method_name)
end

The opposite of ‘should_receive`

@see Methods#should_not_receive

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 75
def should_not_receive(method_name, &block)
  should_receive(method_name, &block).never
end

Initializes the recording a message expectation to be played back against any instance of this object that invokes the submitted method.

@see Methods#should_receive

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 66
def should_receive(method_name, &block)
  @expectation_set = true
  observe!(method_name)
  message_chains.add(method_name, PositiveExpectationChain.new(self, method_name, &block))
end

@private

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 104
def stop_all_observation!
  @observed_methods.each { |method_name| restore_method!(method_name) }
end

Initializes the recording a stub to be played back against any instance of this object that invokes the submitted method.

@see Methods#stub

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 35
def stub(method_name, &block)
  observe!(method_name)
  message_chains.add(method_name, StubChain.new(self, method_name, &block))
end

Initializes the recording a stub chain to be played back against any instance of this object that invokes the method matching the first argument.

@see Methods#stub_chain

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 45
def stub_chain(*method_names_and_optional_return_values, &block)
  normalize_chain(*method_names_and_optional_return_values) do |method_name, args|
    observe!(method_name)
    message_chains.add(method_name, StubChainChain.new(self, *args, &block))
  end
end

Removes any previously recorded stubs, stub_chains or message expectations that use ‘method_name`.

@see Methods#unstub

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 83
def unstub(method_name)
  unless @observed_methods.include?(method_name.to_sym)
    AnyInstance.error_generator.raise_method_not_stubbed_error(method_name)
  end
  message_chains.remove_stub_chains_for!(method_name)
  stubs[method_name].clear
  stop_observing!(method_name) unless message_chains.has_expectation?(method_name)
end

@api private

Used internally to verify that message expectations have been fulfilled.

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 96
def verify
  return unless @expectation_set
  return if message_chains.all_expectations_fulfilled?

  AnyInstance.error_generator.raise_second_instance_received_message_error(message_chains.unfulfilled_expectations)
end

Protected Instance Methods

# File rspec-mocks/lib/rspec/mocks/any_instance/recorder.rb, line 148
def stop_observing!(method_name)
  restore_method!(method_name)
  @observed_methods.delete(method_name)
  super_class_observers_for(method_name).each do |ancestor|
    ::RSpec::Mocks.space.
      any_instance_recorder_for(ancestor).stop_observing!(method_name)
  end
end