Class: RSpec::Mocks::MethodDouble

Inherits:
Object
  • Object
show all
Defined in:
lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb

Direct Known Subclasses

VerifyingMethodDouble

Constant Summary collapse

FROZEN_ERROR_MSG =
/can't modify frozen/

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(object, method_name, proxy) ⇒ MethodDouble

Returns a new instance of MethodDouble.



12
13
14
15
16
17
18
19
20
21
22
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 12

def initialize(object, method_name, proxy)
  @method_name = method_name
  @object = object
  @proxy = proxy

  @original_visibility = nil
  @method_stasher = InstanceMethodStasher.new(object, method_name)
  @method_is_proxied = false
  @expectations = []
  @stubs = []
end

Instance Attribute Details

#expectationsObject (readonly)



9
10
11
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 9

def expectations
  @expectations
end

#method_nameObject (readonly)



9
10
11
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 9

def method_name
  @method_name
end

#method_stasherObject (readonly)



9
10
11
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 9

def method_stasher
  @method_stasher
end

#objectObject (readonly)



9
10
11
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 9

def object
  @object
end

#stubsObject (readonly)



9
10
11
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 9

def stubs
  @stubs
end

Instance Method Details

#add_default_stub(*args, &implementation) ⇒ Object



209
210
211
212
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 209

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) ⇒ Object



159
160
161
162
163
164
165
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 159

def add_expectation(error_generator, expectation_ordering, expected_from, opts, &implementation)
  configure_method
  expectation = message_expectation_class.new(error_generator, expectation_ordering,
                                              expected_from, self, :expectation, opts, &implementation)
  expectations << expectation
  expectation
end

#add_simple_expectation(method_name, response, error_generator, backtrace_line) ⇒ Object



195
196
197
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 195

def add_simple_expectation(method_name, response, error_generator, backtrace_line)
  setup_simple_method_double method_name, response, expectations, error_generator, backtrace_line
end

#add_simple_stub(method_name, response) ⇒ Object

A simple stub can only return a concrete value for a message, and cannot match on arguments. It is used as an optimization over ‘add_stub` / `add_expectation` where it is known in advance that this is all that will be required of a stub, such as when passing attributes to the `double` example method. They do not stash or restore existing method definitions.



190
191
192
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 190

def add_simple_stub(method_name, response)
  setup_simple_method_double method_name, response, stubs
end

#add_stub(error_generator, expectation_ordering, expected_from, opts = {}, &implementation) ⇒ Object



174
175
176
177
178
179
180
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 174

def add_stub(error_generator, expectation_ordering, expected_from, opts={}, &implementation)
  configure_method
  stub = message_expectation_class.new(error_generator, expectation_ordering, expected_from,
                                       self, :stub, opts, &implementation)
  stubs.unshift stub
  stub
end

#build_expectation(error_generator, expectation_ordering) ⇒ Object



168
169
170
171
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 168

def build_expectation(error_generator, expectation_ordering)
  expected_from = IGNORED_BACKTRACE_LINE
  message_expectation_class.new(error_generator, expectation_ordering, expected_from, self)
end

#clearObject



145
146
147
148
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 145

def clear
  expectations.clear
  stubs.clear
end

#configure_methodObject



54
55
56
57
58
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 54

def configure_method
  @original_visibility = visibility
  @method_stasher.stash unless @method_is_proxied
  define_proxy_method
end

#define_proxy_methodObject



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 61

def define_proxy_method
  return if @method_is_proxied

  save_original_implementation_callable!
  definition_target.class_exec(self, method_name, @original_visibility || visibility) do |method_double, method_name, visibility|
    define_method(method_name) do |*args, &block|
      method_double.proxy_method_invoked(self, *args, &block)
    end
    # This can't be `if respond_to?(:ruby2_keywords, true)`,
    # see https://github.com/rspec/rspec-mocks/pull/1385#issuecomment-755340298
    ruby2_keywords(method_name) if Module.private_method_defined?(:ruby2_keywords)
    __send__(visibility, method_name)
  end

  @method_is_proxied = true
rescue RuntimeError, TypeError => e
  # TODO: drop in favor of FrozenError in ruby 2.5+
  #  RuntimeError (and FrozenError) for ruby 2.x
  #  TypeError for ruby 1.x
  if (defined?(FrozenError) && e.is_a?(FrozenError)) || FROZEN_ERROR_MSG === e.message
    raise ArgumentError, "Cannot proxy frozen objects, rspec-mocks relies on proxies for method stubbing and expectations."
  end
  raise
end

#message_expectation_classObject

The type of message expectation to create has been extracted to its own method so that subclasses can override it.



154
155
156
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 154

def message_expectation_class
  MessageExpectation
end

#object_singleton_classObject



49
50
51
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 49

def object_singleton_class
  class << @object; self; end
end

#original_implementation_callableObject Also known as: save_original_implementation_callable!



24
25
26
27
28
29
30
31
32
33
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 24

def original_implementation_callable
  # If original method is not present, uses the `method_missing`
  # handler of the object. This accounts for cases where the user has not
  # correctly defined `respond_to?`, and also 1.8 which does not provide
  # method handles for missing methods even if `respond_to?` is correct.
  @original_implementation_callable ||= original_method ||
    Proc.new do |*args, &block|
      @object.__send__(:method_missing, @method_name, *args, &block)
    end
end

#original_methodObject



37
38
39
40
41
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 37

def original_method
  @original_method ||=
    @method_stasher.original_method ||
    @proxy.original_method_handle_for(method_name)
end

#proxy_method_invoked(_obj, *args, &block) ⇒ Object

The implementation of the proxied method. Subclasses may override this method to perform additional operations.



90
91
92
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 90

def proxy_method_invoked(_obj, *args, &block)
  @proxy.message_received method_name, *args, &block
end

#raise_method_not_stubbed_errorObject



226
227
228
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 226

def raise_method_not_stubbed_error
  RSpec::Mocks.error_generator.raise_method_not_stubbed_error(method_name)
end

#remove_stubObject



215
216
217
218
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 215

def remove_stub
  raise_method_not_stubbed_error if stubs.empty?
  remove_stub_if_present
end

#remove_stub_if_presentObject



221
222
223
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 221

def remove_stub_if_present
  expectations.empty? ? reset : stubs.clear
end

#resetObject



139
140
141
142
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 139

def reset
  restore_original_method
  clear
end

#restore_original_methodObject



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 96

def restore_original_method
  return unless @method_is_proxied

  remove_method_from_definition_target
  @method_stasher.restore if @method_stasher.method_is_stashed?
  restore_original_visibility

  @method_is_proxied = false
rescue RuntimeError, TypeError => e
  # TODO: drop in favor of FrozenError in ruby 2.5+
  #  RuntimeError (and FrozenError) for ruby 2.x
  #  TypeError for ruby 1.x
  if (defined?(FrozenError) && e.is_a?(FrozenError)) || FROZEN_ERROR_MSG === e.message
    return show_frozen_warning
  end
  raise
end

#restore_original_visibilityObject



126
127
128
129
130
131
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 126

def restore_original_visibility
  return unless @original_visibility &&
    MethodReference.method_defined_at_any_visibility?(object_singleton_class, @method_name)

  object_singleton_class.__send__(@original_visibility, method_name)
end

#setup_simple_method_double(method_name, response, collection, error_generator = nil, backtrace_line = nil) ⇒ Object



200
201
202
203
204
205
206
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 200

def setup_simple_method_double(method_name, response, collection, error_generator=nil, backtrace_line=nil)
  define_proxy_method

  me = SimpleMessageExpectation.new(method_name, response, error_generator, backtrace_line)
  collection.unshift me
  me
end

#show_frozen_warningObject



115
116
117
118
119
120
121
122
123
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 115

def show_frozen_warning
  RSpec.warn_with(
    "WARNING: rspec-mocks was unable to restore the original `#{@method_name}` " \
    "method on #{@object.inspect} because it has been frozen.  If you reuse this " \
    "object, `#{@method_name}` will continue to respond with its stub implementation.",
    :call_site                      => nil,
    :use_spec_location_as_call_site => true
  )
end

#verifyObject



134
135
136
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 134

def verify
  expectations.each { |e| e.verify_messages_received }
end

#visibilityObject



44
45
46
# File 'lib/rubypitaya/app-template/vendor/bundle/ruby/3.1.0/gems/rspec-mocks-3.12.2/lib/rspec/mocks/method_double.rb', line 44

def visibility
  @proxy.visibility_for(@method_name)
end