moduleRSpecmoduleMocksmoduleAnyInstance# 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 ChainclassRecorder# @privateattr_reader:message_chains,:stubsdefinitialize(klass)@message_chains=MessageChains.new@stubs=Hash.new{|hash,key|hash[key]=[]}@observed_methods=[]@played_methods={}@klass=klass@expectation_set=falseend# Initializes the recording a stub to be played back against any# instance of this object that invokes the submitted method.## @see Methods#stubdefstub(method_name_or_method_map,&block)ifmethod_name_or_method_map.is_a?(Hash)method_name_or_method_map.eachdo|method_name,return_value|stub(method_name).and_return(return_value)endelseobserve!(method_name_or_method_map)message_chains.add(method_name_or_method_map,StubChain.new(self,method_name_or_method_map,&block))endend# 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_chaindefstub_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))endend# Initializes the recording a message expectation to be played back# against any instance of this object that invokes the submitted# method.## @see Methods#should_receivedefshould_receive(method_name,&block)@expectation_set=trueobserve!(method_name)message_chains.add(method_name,ExpectationChain.new(self,method_name,&block))enddefshould_not_receive(method_name,&block)should_receive(method_name,&block).neverend# Removes any previously recorded stubs, stub_chains or message# expectations that use `method_name`.## @see Methods#unstubdefunstub(method_name)unless@observed_methods.include?(method_name.to_sym)raiseRSpec::Mocks::MockExpectationError,"The method `#{method_name}` was not stubbed or was already unstubbed"endmessage_chains.remove_stub_chains_for!(method_name)::RSpec::Mocks.proxies_of(@klass).eachdo|proxy|stubs[method_name].each{|stub|proxy.remove_single_stub(method_name,stub)}endstubs[method_name].clearstop_observing!(method_name)unlessmessage_chains.has_expectation?(method_name)end# @api private## Used internally to verify that message expectations have been# fulfilled.defverifyif@expectation_set&&!message_chains.all_expectations_fulfilled?raiseRSpec::Mocks::MockExpectationError,"Exactly one instance should have received the following message(s) but didn't: #{message_chains.unfulfilled_expectations.sort.join(', ')}"endend# @privatedefstub!(*)raise"stub! is not supported on any_instance. Use stub instead."end# @privatedefunstub!(*)raise"unstub! is not supported on any_instance. Use unstub instead."end# @privatedefstop_all_observation!@observed_methods.each{|method_name|restore_method!(method_name)}end# @privatedefplayback!(instance,method_name)RSpec::Mocks.space.ensure_registered(instance)message_chains.playback!(instance,method_name)@played_methods[method_name]=instancereceived_expected_message!(method_name)ifmessage_chains.has_expectation?(method_name)end# @privatedefinstance_that_received(method_name)@played_methods[method_name]enddefbuild_alias_method_name(method_name)"__#{method_name}_without_any_instance__"enddefalready_observing?(method_name)@observed_methods.include?(method_name)endprivatedefnormalize_chain(*args)args.shift.to_s.split('.').map{|s|s.to_sym}.reverse.each{|a|args.unshifta}yieldargs.first,argsenddefreceived_expected_message!(method_name)message_chains.received_expected_message!(method_name)restore_method!(method_name)mark_invoked!(method_name)enddefrestore_method!(method_name)ifpublic_protected_or_private_method_defined?(build_alias_method_name(method_name))restore_original_method!(method_name)elseremove_dummy_method!(method_name)endenddefrestore_original_method!(method_name)alias_method_name=build_alias_method_name(method_name)@klass.class_evaldoremove_methodmethod_namealias_methodmethod_name,alias_method_nameremove_methodalias_method_nameendenddefremove_dummy_method!(method_name)@klass.class_evaldoremove_methodmethod_nameendenddefbackup_method!(method_name)alias_method_name=build_alias_method_name(method_name)@klass.class_evaldoalias_methodalias_method_name,method_nameendifpublic_protected_or_private_method_defined?(method_name)enddefpublic_protected_or_private_method_defined?(method_name)@klass.method_defined?(method_name)||@klass.private_method_defined?(method_name)enddefstop_observing!(method_name)restore_method!(method_name)@observed_methods.delete(method_name)enddefobserve!(method_name)stop_observing!(method_name)ifalready_observing?(method_name)@observed_methods<<method_namebackup_method!(method_name)@klass.class_eval(<<-EOM,__FILE__,__LINE__+1)
def #{method_name}(*args, &blk)
klass = ::RSpec::Mocks.method_handle_for(self, :#{method_name}).owner
::RSpec::Mocks.any_instance_recorder_for(klass).playback!(self, :#{method_name})
self.__send__(:#{method_name}, *args, &blk)
end
EOMenddefmark_invoked!(method_name)backup_method!(method_name)@klass.class_eval(<<-EOM,__FILE__,__LINE__+1)
def #{method_name}(*args, &blk)
method_name = :#{method_name}
klass = ::RSpec::Mocks.method_handle_for(self, :#{method_name}).owner
invoked_instance = ::RSpec::Mocks.any_instance_recorder_for(klass).instance_that_received(method_name)
raise RSpec::Mocks::MockExpectationError, "The message '#{method_name}' was received by \#{self.inspect} but has already been received by \#{invoked_instance}"
end
EOMendendendendend