rspec-mocks 3.0.4 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Changelog.md +26 -0
- data/README.md +29 -15
- data/lib/rspec/mocks/any_instance/chain.rb +2 -2
- data/lib/rspec/mocks/any_instance/expectation_chain.rb +2 -3
- data/lib/rspec/mocks/any_instance/message_chains.rb +8 -7
- data/lib/rspec/mocks/any_instance/proxy.rb +2 -2
- data/lib/rspec/mocks/any_instance/recorder.rb +27 -25
- data/lib/rspec/mocks/any_instance/stub_chain.rb +3 -5
- data/lib/rspec/mocks/argument_list_matcher.rb +4 -4
- data/lib/rspec/mocks/argument_matchers.rb +23 -5
- data/lib/rspec/mocks/configuration.rb +3 -10
- data/lib/rspec/mocks/error_generator.rb +33 -27
- data/lib/rspec/mocks/example_methods.rb +74 -6
- data/lib/rspec/mocks/instance_method_stasher.rb +5 -5
- data/lib/rspec/mocks/matchers/have_received.rb +7 -8
- data/lib/rspec/mocks/matchers/receive.rb +8 -8
- data/lib/rspec/mocks/matchers/receive_message_chain.rb +4 -5
- data/lib/rspec/mocks/matchers/receive_messages.rb +6 -7
- data/lib/rspec/mocks/message_chain.rb +5 -5
- data/lib/rspec/mocks/message_expectation.rb +56 -28
- data/lib/rspec/mocks/method_double.rb +15 -12
- data/lib/rspec/mocks/method_reference.rb +8 -7
- data/lib/rspec/mocks/mutate_const.rb +26 -100
- data/lib/rspec/mocks/object_reference.rb +12 -13
- data/lib/rspec/mocks/order_group.rb +4 -5
- data/lib/rspec/mocks/proxy.rb +31 -25
- data/lib/rspec/mocks/space.rb +24 -24
- data/lib/rspec/mocks/syntax.rb +8 -8
- data/lib/rspec/mocks/targets.rb +6 -6
- data/lib/rspec/mocks/test_double.rb +3 -3
- data/lib/rspec/mocks/verifying_double.rb +10 -12
- data/lib/rspec/mocks/verifying_message_expecation.rb +15 -13
- data/lib/rspec/mocks/verifying_proxy.rb +11 -15
- data/lib/rspec/mocks/version.rb +1 -1
- metadata +5 -5
- metadata.gz.sig +0 -0
@@ -59,7 +59,7 @@ module RSpec
|
|
59
59
|
define_method(method_name) do |*args, &block|
|
60
60
|
method_double.proxy_method_invoked(self, *args, &block)
|
61
61
|
end
|
62
|
-
|
62
|
+
__send__(visibility, method_name)
|
63
63
|
end
|
64
64
|
|
65
65
|
@method_is_proxied = true
|
@@ -69,7 +69,7 @@ module RSpec
|
|
69
69
|
# method to perform additional operations.
|
70
70
|
#
|
71
71
|
# @private
|
72
|
-
def proxy_method_invoked(
|
72
|
+
def proxy_method_invoked(_obj, *args, &block)
|
73
73
|
@proxy.message_received method_name, *args, &block
|
74
74
|
end
|
75
75
|
|
@@ -80,9 +80,7 @@ module RSpec
|
|
80
80
|
|
81
81
|
definition_target.__send__(:remove_method, @method_name)
|
82
82
|
|
83
|
-
if @method_stasher.method_is_stashed?
|
84
|
-
@method_stasher.restore
|
85
|
-
end
|
83
|
+
@method_stasher.restore if @method_stasher.method_is_stashed?
|
86
84
|
restore_original_visibility
|
87
85
|
|
88
86
|
@method_is_proxied = false
|
@@ -91,7 +89,9 @@ module RSpec
|
|
91
89
|
# @private
|
92
90
|
def show_frozen_warning
|
93
91
|
RSpec.warn_with(
|
94
|
-
"WARNING: rspec-mocks was unable to restore the original `#{@method_name}`
|
92
|
+
"WARNING: rspec-mocks was unable to restore the original `#{@method_name}` " \
|
93
|
+
"method on #{@object.inspect} because it has been frozen. If you reuse this " \
|
94
|
+
"object, `#{@method_name}` will continue to respond with its stub implementation.",
|
95
95
|
:call_site => nil,
|
96
96
|
:use_spec_location_as_call_site => true
|
97
97
|
)
|
@@ -107,7 +107,7 @@ module RSpec
|
|
107
107
|
|
108
108
|
# @private
|
109
109
|
def verify
|
110
|
-
expectations.each {|e| e.verify_messages_received}
|
110
|
+
expectations.each { |e| e.verify_messages_received }
|
111
111
|
end
|
112
112
|
|
113
113
|
# @private
|
@@ -134,7 +134,7 @@ module RSpec
|
|
134
134
|
def add_expectation(error_generator, expectation_ordering, expected_from, opts, &implementation)
|
135
135
|
configure_method
|
136
136
|
expectation = message_expectation_class.new(error_generator, expectation_ordering,
|
137
|
-
|
137
|
+
expected_from, self, :expectation, opts, &implementation)
|
138
138
|
expectations << expectation
|
139
139
|
expectation
|
140
140
|
end
|
@@ -149,7 +149,7 @@ module RSpec
|
|
149
149
|
def add_stub(error_generator, expectation_ordering, expected_from, opts={}, &implementation)
|
150
150
|
configure_method
|
151
151
|
stub = message_expectation_class.new(error_generator, expectation_ordering, expected_from,
|
152
|
-
|
152
|
+
self, :stub, opts, &implementation)
|
153
153
|
stubs.unshift stub
|
154
154
|
stub
|
155
155
|
end
|
@@ -172,7 +172,7 @@ module RSpec
|
|
172
172
|
end
|
173
173
|
|
174
174
|
# @private
|
175
|
-
def setup_simple_method_double(method_name, response, collection, error_generator
|
175
|
+
def setup_simple_method_double(method_name, response, collection, error_generator=nil, backtrace_line=nil)
|
176
176
|
define_proxy_method
|
177
177
|
|
178
178
|
me = SimpleMessageExpectation.new(method_name, response, error_generator, backtrace_line)
|
@@ -202,8 +202,6 @@ module RSpec
|
|
202
202
|
raise MockExpectationError, "The method `#{method_name}` was not stubbed or was already unstubbed"
|
203
203
|
end
|
204
204
|
|
205
|
-
private
|
206
|
-
|
207
205
|
# In Ruby 2.0.0 and above prepend will alter the method lookup chain.
|
208
206
|
# We use an object's singleton class to define method doubles upon,
|
209
207
|
# however if the object has had it's singleton class (as opposed to
|
@@ -216,6 +214,9 @@ module RSpec
|
|
216
214
|
# of our own.
|
217
215
|
#
|
218
216
|
if Support::RubyFeatures.module_prepends_supported?
|
217
|
+
|
218
|
+
private
|
219
|
+
|
219
220
|
# We subclass `Module` in order to be able to easily detect our prepended module.
|
220
221
|
RSpecPrependedModule = Class.new(Module)
|
221
222
|
|
@@ -247,6 +248,8 @@ module RSpec
|
|
247
248
|
|
248
249
|
else
|
249
250
|
|
251
|
+
private
|
252
|
+
|
250
253
|
def definition_target
|
251
254
|
object_singleton_class
|
252
255
|
end
|
@@ -27,7 +27,7 @@ module RSpec
|
|
27
27
|
# cases when we don't know if a method is implemented and
|
28
28
|
# both `implemented?` and `unimplemented?` will return false.
|
29
29
|
def unimplemented?
|
30
|
-
@object_reference.when_loaded do |
|
30
|
+
@object_reference.when_loaded do |_m|
|
31
31
|
return !implemented?
|
32
32
|
end
|
33
33
|
|
@@ -44,9 +44,8 @@ module RSpec
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def with_signature
|
47
|
-
|
48
|
-
|
49
|
-
end
|
47
|
+
return unless (original = original_method)
|
48
|
+
yield Support::MethodSignature.new(original)
|
50
49
|
end
|
51
50
|
|
52
51
|
def visibility
|
@@ -59,7 +58,7 @@ module RSpec
|
|
59
58
|
:public
|
60
59
|
end
|
61
60
|
|
62
|
-
|
61
|
+
private
|
63
62
|
|
64
63
|
def original_method
|
65
64
|
@object_reference.when_loaded do |m|
|
@@ -98,7 +97,8 @@ module RSpec
|
|
98
97
|
|
99
98
|
# @private
|
100
99
|
class InstanceMethodReference < MethodReference
|
101
|
-
|
100
|
+
private
|
101
|
+
|
102
102
|
def method_implemented?(mod)
|
103
103
|
MethodReference.method_defined_at_any_visibility?(mod, @method_name)
|
104
104
|
end
|
@@ -133,7 +133,8 @@ module RSpec
|
|
133
133
|
|
134
134
|
# @private
|
135
135
|
class ObjectMethodReference < MethodReference
|
136
|
-
|
136
|
+
private
|
137
|
+
|
137
138
|
def method_implemented?(object)
|
138
139
|
object.respond_to?(@method_name, true)
|
139
140
|
end
|
@@ -1,85 +1,11 @@
|
|
1
|
+
RSpec::Support.require_rspec_support 'recursive_const_methods'
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module Mocks
|
3
|
-
# Provides recursive constant lookup methods useful for
|
4
|
-
# constant stubbing.
|
5
|
-
#
|
6
|
-
# @private
|
7
|
-
module RecursiveConstMethods
|
8
|
-
# We only want to consider constants that are defined directly on a
|
9
|
-
# particular module, and not include top-level/inherited constants.
|
10
|
-
# Unfortunately, the constant API changed between 1.8 and 1.9, so
|
11
|
-
# we need to conditionally define methods to ignore the top-level/inherited
|
12
|
-
# constants.
|
13
|
-
#
|
14
|
-
# Given:
|
15
|
-
# class A; B = 1; end
|
16
|
-
# class C < A; end
|
17
|
-
#
|
18
|
-
# On 1.8:
|
19
|
-
# - C.const_get("Hash") # => ::Hash
|
20
|
-
# - C.const_defined?("Hash") # => false
|
21
|
-
# - C.constants # => ["B"]
|
22
|
-
# - None of these methods accept the extra `inherit` argument
|
23
|
-
# On 1.9:
|
24
|
-
# - C.const_get("Hash") # => ::Hash
|
25
|
-
# - C.const_defined?("Hash") # => true
|
26
|
-
# - C.const_get("Hash", false) # => raises NameError
|
27
|
-
# - C.const_defined?("Hash", false) # => false
|
28
|
-
# - C.constants # => [:B]
|
29
|
-
# - C.constants(false) #=> []
|
30
|
-
if Module.method(:const_defined?).arity == 1
|
31
|
-
def const_defined_on?(mod, const_name)
|
32
|
-
mod.const_defined?(const_name)
|
33
|
-
end
|
34
|
-
|
35
|
-
def get_const_defined_on(mod, const_name)
|
36
|
-
if const_defined_on?(mod, const_name)
|
37
|
-
return mod.const_get(const_name)
|
38
|
-
end
|
39
|
-
|
40
|
-
raise NameError, "uninitialized constant #{mod.name}::#{const_name}"
|
41
|
-
end
|
42
|
-
|
43
|
-
def constants_defined_on(mod)
|
44
|
-
mod.constants.select { |c| const_defined_on?(mod, c) }
|
45
|
-
end
|
46
|
-
else
|
47
|
-
def const_defined_on?(mod, const_name)
|
48
|
-
mod.const_defined?(const_name, false)
|
49
|
-
end
|
50
|
-
|
51
|
-
def get_const_defined_on(mod, const_name)
|
52
|
-
mod.const_get(const_name, false)
|
53
|
-
end
|
54
|
-
|
55
|
-
def constants_defined_on(mod)
|
56
|
-
mod.constants(false)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def recursive_const_get(const_name)
|
61
|
-
normalize_const_name(const_name).split('::').inject(Object) do |mod, name|
|
62
|
-
get_const_defined_on(mod, name)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def recursive_const_defined?(const_name)
|
67
|
-
normalize_const_name(const_name).split('::').inject([Object, '']) do |(mod, full_name), name|
|
68
|
-
yield(full_name, name) if block_given? && !(Module === mod)
|
69
|
-
return false unless const_defined_on?(mod, name)
|
70
|
-
[get_const_defined_on(mod, name), [mod, name].join('::')]
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def normalize_const_name(const_name)
|
75
|
-
const_name.sub(/\A::/, '')
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
5
|
# Provides information about constants that may (or may not)
|
80
6
|
# have been mutated by rspec-mocks.
|
81
7
|
class Constant
|
82
|
-
extend RecursiveConstMethods
|
8
|
+
extend Support::RecursiveConstMethods
|
83
9
|
|
84
10
|
# @api private
|
85
11
|
def initialize(name)
|
@@ -154,7 +80,7 @@ module RSpec
|
|
154
80
|
|
155
81
|
# Provides a means to stub constants.
|
156
82
|
class ConstantMutator
|
157
|
-
extend RecursiveConstMethods
|
83
|
+
extend Support::RecursiveConstMethods
|
158
84
|
|
159
85
|
# Stubs a constant.
|
160
86
|
#
|
@@ -167,12 +93,12 @@ module RSpec
|
|
167
93
|
# examples. This is an alternate public API that is provided
|
168
94
|
# so you can stub constants in other contexts (e.g. helper
|
169
95
|
# classes).
|
170
|
-
def self.stub(constant_name, value, options
|
96
|
+
def self.stub(constant_name, value, options={})
|
171
97
|
mutator = if recursive_const_defined?(constant_name, &raise_on_invalid_const)
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
98
|
+
DefinedConstantReplacer
|
99
|
+
else
|
100
|
+
UndefinedConstantSetter
|
101
|
+
end
|
176
102
|
|
177
103
|
mutate(mutator.new(constant_name, value, options[:transfer_nested_constants]))
|
178
104
|
value
|
@@ -188,7 +114,7 @@ module RSpec
|
|
188
114
|
# so you can hide constants in other contexts (e.g. helper
|
189
115
|
# classes).
|
190
116
|
def self.hide(constant_name)
|
191
|
-
mutate(ConstantHider.new(constant_name, nil, {
|
117
|
+
mutate(ConstantHider.new(constant_name, nil, {}))
|
192
118
|
nil
|
193
119
|
end
|
194
120
|
|
@@ -196,7 +122,7 @@ module RSpec
|
|
196
122
|
#
|
197
123
|
# @private
|
198
124
|
class BaseMutator
|
199
|
-
include RecursiveConstMethods
|
125
|
+
include Support::RecursiveConstMethods
|
200
126
|
|
201
127
|
attr_reader :original_value, :full_constant_name
|
202
128
|
|
@@ -227,7 +153,7 @@ module RSpec
|
|
227
153
|
# @private
|
228
154
|
class ConstantHider < BaseMutator
|
229
155
|
def mutate
|
230
|
-
return unless @defined = recursive_const_defined?(full_constant_name)
|
156
|
+
return unless (@defined = recursive_const_defined?(full_constant_name))
|
231
157
|
@context = recursive_const_get(@context_parts.join('::'))
|
232
158
|
@original_value = get_const_defined_on(@context, @const_name)
|
233
159
|
|
@@ -298,12 +224,12 @@ module RSpec
|
|
298
224
|
return [] unless should_transfer_nested_constants?
|
299
225
|
|
300
226
|
{ @original_value => "the original value", @mutated_value => "the stubbed value" }.each do |value, description|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
227
|
+
next if value.respond_to?(:constants)
|
228
|
+
|
229
|
+
raise ArgumentError,
|
230
|
+
"Cannot transfer nested constants for #{@full_constant_name} " \
|
231
|
+
"since #{description} is not a class or module and only classes " \
|
232
|
+
"and modules support nested constants."
|
307
233
|
end
|
308
234
|
|
309
235
|
if Array === @transfer_nested_constants
|
@@ -313,9 +239,9 @@ module RSpec
|
|
313
239
|
if undefined_constants.any?
|
314
240
|
available_constants = constants_defined_on(@original_value) - @transfer_nested_constants
|
315
241
|
raise ArgumentError,
|
316
|
-
|
317
|
-
|
318
|
-
|
242
|
+
"Cannot transfer nested constant(s) #{undefined_constants.join(' and ')} " \
|
243
|
+
"for #{@full_constant_name} since they are not defined. Did you mean " \
|
244
|
+
"#{available_constants.join(' or ')}?"
|
319
245
|
end
|
320
246
|
|
321
247
|
@transfer_nested_constants
|
@@ -363,10 +289,10 @@ module RSpec
|
|
363
289
|
|
364
290
|
def name_for(parent, name)
|
365
291
|
root = if parent == Object
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
292
|
+
''
|
293
|
+
else
|
294
|
+
parent.name
|
295
|
+
end
|
370
296
|
root + '::' + name
|
371
297
|
end
|
372
298
|
end
|
@@ -389,7 +315,7 @@ module RSpec
|
|
389
315
|
# @api private
|
390
316
|
def self.raise_on_invalid_const
|
391
317
|
lambda do |const_name, failed_name|
|
392
|
-
raise "Cannot stub constant #{failed_name} on #{const_name} "
|
318
|
+
raise "Cannot stub constant #{failed_name} on #{const_name} " \
|
393
319
|
"since #{const_name} is not a module."
|
394
320
|
end
|
395
321
|
end
|
@@ -1,21 +1,20 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Mocks
|
3
|
-
|
4
3
|
# @private
|
5
4
|
class ObjectReference
|
6
5
|
# Returns an appropriate Object or Module reference based
|
7
6
|
# on the given argument.
|
8
|
-
def self.for(object_module_or_name, allow_direct_object_refs
|
7
|
+
def self.for(object_module_or_name, allow_direct_object_refs=false)
|
9
8
|
case object_module_or_name
|
10
|
-
|
11
|
-
|
9
|
+
when Module then DirectModuleReference.new(object_module_or_name)
|
10
|
+
when String then NamedObjectReference.new(object_module_or_name)
|
11
|
+
else
|
12
|
+
if allow_direct_object_refs
|
13
|
+
DirectObjectReference.new(object_module_or_name)
|
12
14
|
else
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
raise ArgumentError,
|
17
|
-
"Module or String expected, got #{object_module_or_name.inspect}"
|
18
|
-
end
|
15
|
+
raise ArgumentError,
|
16
|
+
"Module or String expected, got #{object_module_or_name.inspect}"
|
17
|
+
end
|
19
18
|
end
|
20
19
|
end
|
21
20
|
end
|
@@ -35,7 +34,7 @@ module RSpec
|
|
35
34
|
|
36
35
|
def const_to_replace
|
37
36
|
raise ArgumentError,
|
38
|
-
|
37
|
+
"Can not perform constant replacement with an object."
|
39
38
|
end
|
40
39
|
|
41
40
|
def defined?
|
@@ -78,11 +77,11 @@ module RSpec
|
|
78
77
|
end
|
79
78
|
alias description const_to_replace
|
80
79
|
|
81
|
-
def when_loaded(&
|
80
|
+
def when_loaded(&_block)
|
82
81
|
yield object if object
|
83
82
|
end
|
84
83
|
|
85
|
-
|
84
|
+
private
|
86
85
|
|
87
86
|
def object
|
88
87
|
@object ||= Constant.original(@const_name).original_value
|
@@ -25,10 +25,10 @@ module RSpec
|
|
25
25
|
# @private
|
26
26
|
def consume
|
27
27
|
remaining_expectations.each_with_index do |expectation, index|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
next unless expectation.ordered?
|
29
|
+
|
30
|
+
@index += index + 1
|
31
|
+
return expectation
|
32
32
|
end
|
33
33
|
nil
|
34
34
|
end
|
@@ -76,7 +76,6 @@ module RSpec
|
|
76
76
|
def expectation_for(message)
|
77
77
|
@expectations.find { |e| message == e }
|
78
78
|
end
|
79
|
-
|
80
79
|
end
|
81
80
|
end
|
82
81
|
end
|
data/lib/rspec/mocks/proxy.rb
CHANGED
@@ -9,7 +9,7 @@ module RSpec
|
|
9
9
|
end
|
10
10
|
|
11
11
|
# @private
|
12
|
-
def ensure_implemented(*
|
12
|
+
def ensure_implemented(*_args)
|
13
13
|
# noop for basic proxies, see VerifyingProxy for behaviour.
|
14
14
|
end
|
15
15
|
|
@@ -42,7 +42,7 @@ module RSpec
|
|
42
42
|
end
|
43
43
|
|
44
44
|
# @private
|
45
|
-
def original_method_handle_for(
|
45
|
+
def original_method_handle_for(_message)
|
46
46
|
nil
|
47
47
|
end
|
48
48
|
|
@@ -89,20 +89,19 @@ module RSpec
|
|
89
89
|
end
|
90
90
|
|
91
91
|
@messages_received.each do |(actual_method_name, args, _)|
|
92
|
-
|
93
|
-
expectation.invoke(nil)
|
94
|
-
block.call(*args) if block
|
95
|
-
end
|
96
|
-
end
|
92
|
+
next unless expectation.matches?(actual_method_name, *args)
|
97
93
|
|
94
|
+
expectation.invoke(nil)
|
95
|
+
block.call(*args) if block
|
96
|
+
end
|
98
97
|
end
|
99
98
|
|
100
99
|
# @private
|
101
100
|
def check_for_unexpected_arguments(expectation)
|
102
101
|
@messages_received.each do |(method_name, args, _)|
|
103
|
-
|
104
|
-
|
105
|
-
|
102
|
+
next unless expectation.matches_name_but_not_args(method_name, *args)
|
103
|
+
|
104
|
+
raise_unexpected_message_args_error(expectation, *args)
|
106
105
|
end
|
107
106
|
end
|
108
107
|
|
@@ -129,7 +128,7 @@ module RSpec
|
|
129
128
|
|
130
129
|
# @private
|
131
130
|
def verify
|
132
|
-
@method_doubles.each_value {|d| d.verify}
|
131
|
+
@method_doubles.each_value { |d| d.verify }
|
133
132
|
end
|
134
133
|
|
135
134
|
# @private
|
@@ -139,12 +138,12 @@ module RSpec
|
|
139
138
|
|
140
139
|
# @private
|
141
140
|
def received_message?(method_name, *args, &block)
|
142
|
-
@messages_received.any? {|array| array == [method_name, args, block]}
|
141
|
+
@messages_received.any? { |array| array == [method_name, args, block] }
|
143
142
|
end
|
144
143
|
|
145
144
|
# @private
|
146
145
|
def has_negative_expectation?(message)
|
147
|
-
method_double_for(message).expectations.
|
146
|
+
method_double_for(message).expectations.find { |expectation| expectation.negative_expectation_for?(message) }
|
148
147
|
end
|
149
148
|
|
150
149
|
# @private
|
@@ -162,16 +161,19 @@ module RSpec
|
|
162
161
|
|
163
162
|
if (stub && expectation && expectation.called_max_times?) || (stub && !expectation)
|
164
163
|
expectation.increase_actual_received_count! if expectation && expectation.actual_received_count_matters?
|
165
|
-
if expectation = find_almost_matching_expectation(message, *args)
|
164
|
+
if (expectation = find_almost_matching_expectation(message, *args))
|
166
165
|
expectation.advise(*args) unless expectation.expected_messages_received?
|
167
166
|
end
|
168
167
|
stub.invoke(nil, *args, &block)
|
169
168
|
elsif expectation
|
170
169
|
expectation.invoke(stub, *args, &block)
|
171
|
-
elsif expectation = find_almost_matching_expectation(message, *args)
|
170
|
+
elsif (expectation = find_almost_matching_expectation(message, *args))
|
172
171
|
expectation.advise(*args) if null_object? unless expectation.expected_messages_received?
|
173
|
-
|
174
|
-
|
172
|
+
|
173
|
+
if null_object? || !has_negative_expectation?(message)
|
174
|
+
raise_unexpected_message_args_error(expectation, *args)
|
175
|
+
end
|
176
|
+
elsif (stub = find_almost_matching_stub(message, *args))
|
175
177
|
stub.advise(*args)
|
176
178
|
raise_missing_default_stub_error(stub, *args)
|
177
179
|
elsif Class === @object
|
@@ -197,7 +199,7 @@ module RSpec
|
|
197
199
|
end
|
198
200
|
|
199
201
|
# @private
|
200
|
-
def visibility_for(
|
202
|
+
def visibility_for(_method_name)
|
201
203
|
# This is the default (for test doubles). Subclasses override this.
|
202
204
|
:public
|
203
205
|
end
|
@@ -206,9 +208,13 @@ module RSpec
|
|
206
208
|
def prepended_modules_of_singleton_class
|
207
209
|
@prepended_modules_of_singleton_class ||= begin
|
208
210
|
singleton_class = @object.singleton_class
|
209
|
-
singleton_class.ancestors
|
210
|
-
|
211
|
-
|
211
|
+
ancestors = singleton_class.ancestors
|
212
|
+
|
213
|
+
# `|| 0` is necessary for Ruby 2.0, where the singleton class
|
214
|
+
# is only in the ancestor list when there are prepended modules.
|
215
|
+
singleton_index = ancestors.index(singleton_class) || 0
|
216
|
+
|
217
|
+
ancestors[0, singleton_index]
|
212
218
|
end
|
213
219
|
end
|
214
220
|
end
|
@@ -244,11 +250,11 @@ module RSpec
|
|
244
250
|
end
|
245
251
|
|
246
252
|
def find_matching_method_stub(method_name, *args)
|
247
|
-
method_double_for(method_name).stubs.find {|stub| stub.matches?(method_name, *args)}
|
253
|
+
method_double_for(method_name).stubs.find { |stub| stub.matches?(method_name, *args) }
|
248
254
|
end
|
249
255
|
|
250
256
|
def find_almost_matching_stub(method_name, *args)
|
251
|
-
method_double_for(method_name).stubs.find {|stub| stub.matches_name_but_not_args(method_name, *args)}
|
257
|
+
method_double_for(method_name).stubs.find { |stub| stub.matches_name_but_not_args(method_name, *args) }
|
252
258
|
end
|
253
259
|
end
|
254
260
|
|
@@ -295,7 +301,7 @@ module RSpec
|
|
295
301
|
end
|
296
302
|
|
297
303
|
def reset
|
298
|
-
@method_doubles.each_value {|d| d.reset}
|
304
|
+
@method_doubles.each_value { |d| d.reset }
|
299
305
|
super
|
300
306
|
end
|
301
307
|
|
@@ -415,7 +421,7 @@ module RSpec
|
|
415
421
|
|
416
422
|
private
|
417
423
|
|
418
|
-
def warn
|
424
|
+
def warn(method_name)
|
419
425
|
source = CallerFilter.first_non_rspec_line
|
420
426
|
Kernel.warn("An expectation of :#{method_name} was set on nil. Called from #{source}. Use allow_message_expectations_on_nil to disable warnings.")
|
421
427
|
end
|