Class: RSpec::Mocks::MethodDouble

Inherits:
Object
  • Object
show all
Defined in:
lib/rspec/mocks/method_double.rb

Direct Known Subclasses

VerifyingMethodDouble

Constant Summary

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (MethodDouble) initialize(object, method_name, proxy)

Returns a new instance of MethodDouble



9
10
11
12
13
14
15
16
17
18
19
# File 'lib/rspec/mocks/method_double.rb', line 9

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

- (Object) expectations (readonly)



6
7
8
# File 'lib/rspec/mocks/method_double.rb', line 6

def expectations
  @expectations
end

- (Object) method_name (readonly)



6
7
8
# File 'lib/rspec/mocks/method_double.rb', line 6

def method_name
  @method_name
end

- (Object) object (readonly)



6
7
8
# File 'lib/rspec/mocks/method_double.rb', line 6

def object
  @object
end

- (Object) stubs (readonly)



6
7
8
# File 'lib/rspec/mocks/method_double.rb', line 6

def stubs
  @stubs
end

Instance Method Details

- (Object) add_default_stub(*args, &implementation)



184
185
186
187
# File 'lib/rspec/mocks/method_double.rb', line 184

def add_default_stub(*args, &implementation)
  return if stubs.any?
  add_stub(*args, &implementation)
end

- (Object) add_expectation(error_generator, expectation_ordering, expected_from, opts, &implementation)



134
135
136
137
138
139
140
# File 'lib/rspec/mocks/method_double.rb', line 134

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, 1, opts, &implementation)
  expectations << expectation
  expectation
end

- (Object) add_simple_expectation(method_name, response, error_generator, backtrace_line)



170
171
172
# File 'lib/rspec/mocks/method_double.rb', line 170

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

- (Object) add_simple_stub(method_name, response)

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.



165
166
167
# File 'lib/rspec/mocks/method_double.rb', line 165

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

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



149
150
151
152
153
154
155
# File 'lib/rspec/mocks/method_double.rb', line 149

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, :any, opts, &implementation)
  stubs.unshift stub
  stub
end

- (Object) build_expectation(error_generator, expectation_ordering)



143
144
145
146
# File 'lib/rspec/mocks/method_double.rb', line 143

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

- (Object) clear



120
121
122
123
# File 'lib/rspec/mocks/method_double.rb', line 120

def clear
  expectations.clear
  stubs.clear
end

- (Object) configure_method



47
48
49
50
51
# File 'lib/rspec/mocks/method_double.rb', line 47

def configure_method
  @original_visibility = [visibility, method_name]
  @method_stasher.stash unless @method_is_proxied
  define_proxy_method
end

- (Object) define_proxy_method



54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/rspec/mocks/method_double.rb', line 54

def define_proxy_method
  return if @method_is_proxied

  save_original_method!
  definition_target.class_exec(self, method_name, visibility) do |method_double, method_name, visibility|
    define_method(method_name) do |*args, &block|
      method_double.proxy_method_invoked(self, *args, &block)
    end
    self.__send__ visibility, method_name
  end

  @method_is_proxied = true
end

- (Object) message_expectation_class

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



129
130
131
# File 'lib/rspec/mocks/method_double.rb', line 129

def message_expectation_class
  MessageExpectation
end

- (Object) object_singleton_class



42
43
44
# File 'lib/rspec/mocks/method_double.rb', line 42

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

- (Object) original_method Also known as: save_original_method!



21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/rspec/mocks/method_double.rb', line 21

def original_method
  # 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_method ||=
    @method_stasher.original_method ||
    @proxy.original_method_handle_for(method_name) ||
    Proc.new do |*args, &block|
      @object.__send__(:method_missing, @method_name, *args, &block)
    end
end

- (Object) proxy_method_invoked(obj, *args, &block)

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



72
73
74
# File 'lib/rspec/mocks/method_double.rb', line 72

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

- (Object) raise_method_not_stubbed_error



201
202
203
# File 'lib/rspec/mocks/method_double.rb', line 201

def raise_method_not_stubbed_error
  raise MockExpectationError, "The method `#{method_name}` was not stubbed or was already unstubbed"
end

- (Object) remove_stub



190
191
192
193
# File 'lib/rspec/mocks/method_double.rb', line 190

def remove_stub
  raise_method_not_stubbed_error if stubs.empty?
  remove_stub_if_present
end

- (Object) remove_stub_if_present



196
197
198
# File 'lib/rspec/mocks/method_double.rb', line 196

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

- (Object) reset



114
115
116
117
# File 'lib/rspec/mocks/method_double.rb', line 114

def reset
  restore_original_method
  clear
end

- (Object) restore_original_method



77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/rspec/mocks/method_double.rb', line 77

def restore_original_method
  return show_frozen_warning if object_singleton_class.frozen?
  return unless @method_is_proxied

  definition_target.__send__(:remove_method, @method_name)

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

  @method_is_proxied = false
end

- (Object) restore_original_visibility



101
102
103
104
105
106
# File 'lib/rspec/mocks/method_double.rb', line 101

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)
end

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



175
176
177
178
179
180
181
# File 'lib/rspec/mocks/method_double.rb', line 175

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

- (Object) show_frozen_warning



92
93
94
95
96
97
98
# File 'lib/rspec/mocks/method_double.rb', line 92

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

- (Object) verify



109
110
111
# File 'lib/rspec/mocks/method_double.rb', line 109

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

- (Object) visibility



37
38
39
# File 'lib/rspec/mocks/method_double.rb', line 37

def visibility
  @proxy.visibility_for(@method_name)
end