rspec-mocks 3.0.0.beta1 → 3.0.0.beta2
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.
- data.tar.gz.sig +1 -1
- data/Changelog.md +95 -3
- data/README.md +27 -13
- data/features/README.md +15 -7
- data/features/argument_matchers/README.md +5 -5
- data/features/argument_matchers/explicit.feature +6 -6
- data/features/argument_matchers/general_matchers.feature +4 -4
- data/features/argument_matchers/type_matchers.feature +2 -2
- data/features/message_expectations/README.md +29 -27
- data/features/message_expectations/call_original.feature +0 -1
- data/features/message_expectations/message_chains_using_expect.feature +49 -0
- data/features/method_stubs/README.md +2 -1
- data/features/method_stubs/{any_instance.feature → allow_any_instance_of.feature} +12 -12
- data/features/method_stubs/{stub_chain.feature → receive_message_chain.feature} +3 -3
- data/features/method_stubs/to_ary.feature +1 -1
- data/features/mutating_constants/stub_defined_constant.feature +0 -1
- data/features/outside_rspec/standalone.feature +1 -1
- data/features/spies/spy_pure_mock_method.feature +1 -1
- data/features/test_frameworks/test_unit.feature +21 -10
- data/features/verifying_doubles/README.md +17 -0
- data/features/verifying_doubles/class_doubles.feature +1 -16
- data/features/verifying_doubles/dynamic_classes.feature +0 -1
- data/features/verifying_doubles/{introduction.feature → instance_doubles.feature} +41 -23
- data/features/verifying_doubles/partial_doubles.feature +2 -2
- data/lib/rspec/mocks.rb +69 -82
- data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +35 -0
- data/lib/rspec/mocks/any_instance/expectation_chain.rb +1 -2
- data/lib/rspec/mocks/any_instance/recorder.rb +52 -18
- data/lib/rspec/mocks/any_instance/stub_chain.rb +1 -1
- data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +4 -0
- data/lib/rspec/mocks/argument_list_matcher.rb +10 -44
- data/lib/rspec/mocks/argument_matchers.rb +132 -163
- data/lib/rspec/mocks/configuration.rb +28 -4
- data/lib/rspec/mocks/error_generator.rb +46 -13
- data/lib/rspec/mocks/example_methods.rb +13 -12
- data/lib/rspec/mocks/extensions/marshal.rb +1 -1
- data/lib/rspec/mocks/framework.rb +3 -4
- data/lib/rspec/mocks/instance_method_stasher.rb +2 -3
- data/lib/rspec/mocks/matchers/have_received.rb +8 -6
- data/lib/rspec/mocks/matchers/receive.rb +28 -20
- data/lib/rspec/mocks/matchers/receive_message_chain.rb +65 -0
- data/lib/rspec/mocks/matchers/receive_messages.rb +3 -2
- data/lib/rspec/mocks/message_chain.rb +91 -0
- data/lib/rspec/mocks/message_expectation.rb +86 -80
- data/lib/rspec/mocks/method_double.rb +2 -11
- data/lib/rspec/mocks/method_reference.rb +82 -23
- data/lib/rspec/mocks/method_signature_verifier.rb +207 -0
- data/lib/rspec/mocks/mutate_const.rb +34 -50
- data/lib/rspec/mocks/object_reference.rb +0 -1
- data/lib/rspec/mocks/proxy.rb +70 -13
- data/lib/rspec/mocks/ruby_features.rb +24 -0
- data/lib/rspec/mocks/space.rb +105 -31
- data/lib/rspec/mocks/standalone.rb +2 -2
- data/lib/rspec/mocks/syntax.rb +43 -8
- data/lib/rspec/mocks/targets.rb +16 -7
- data/lib/rspec/mocks/test_double.rb +41 -15
- data/lib/rspec/mocks/verifying_double.rb +51 -4
- data/lib/rspec/mocks/verifying_message_expecation.rb +12 -12
- data/lib/rspec/mocks/verifying_proxy.rb +32 -19
- data/lib/rspec/mocks/version.rb +1 -1
- data/spec/rspec/mocks/and_call_original_spec.rb +28 -7
- data/spec/rspec/mocks/and_return_spec.rb +23 -0
- data/spec/rspec/mocks/and_yield_spec.rb +1 -2
- data/spec/rspec/mocks/any_instance_spec.rb +33 -17
- data/spec/rspec/mocks/array_including_matcher_spec.rb +6 -6
- data/spec/rspec/mocks/before_all_spec.rb +132 -0
- data/spec/rspec/mocks/block_return_value_spec.rb +12 -1
- data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +9 -11
- data/spec/rspec/mocks/configuration_spec.rb +14 -1
- data/spec/rspec/mocks/double_spec.rb +867 -24
- data/spec/rspec/mocks/example_methods_spec.rb +13 -0
- data/spec/rspec/mocks/extensions/marshal_spec.rb +17 -17
- data/spec/rspec/mocks/failing_argument_matchers_spec.rb +29 -1
- data/spec/rspec/mocks/hash_excluding_matcher_spec.rb +12 -12
- data/spec/rspec/mocks/hash_including_matcher_spec.rb +21 -17
- data/spec/rspec/mocks/instance_method_stasher_spec.rb +2 -3
- data/spec/rspec/mocks/matchers/have_received_spec.rb +7 -0
- data/spec/rspec/mocks/matchers/receive_message_chain_spec.rb +198 -0
- data/spec/rspec/mocks/matchers/receive_messages_spec.rb +2 -2
- data/spec/rspec/mocks/matchers/receive_spec.rb +19 -6
- data/spec/rspec/mocks/method_signature_verifier_spec.rb +272 -0
- data/spec/rspec/mocks/methods_spec.rb +0 -1
- data/spec/rspec/mocks/multiple_return_value_spec.rb +2 -2
- data/spec/rspec/mocks/mutate_const_spec.rb +24 -1
- data/spec/rspec/mocks/nil_expectation_warning_spec.rb +6 -22
- data/spec/rspec/mocks/null_object_mock_spec.rb +13 -7
- data/spec/rspec/mocks/options_hash_spec.rb +3 -3
- data/spec/rspec/mocks/{partial_mock_spec.rb → partial_double_spec.rb} +5 -2
- data/spec/rspec/mocks/{partial_mock_using_mocks_directly_spec.rb → partial_double_using_mocks_directly_spec.rb} +1 -1
- data/spec/rspec/mocks/passing_argument_matchers_spec.rb +18 -0
- data/spec/rspec/mocks/serialization_spec.rb +1 -0
- data/spec/rspec/mocks/space_spec.rb +218 -7
- data/spec/rspec/mocks/stub_chain_spec.rb +6 -0
- data/spec/rspec/mocks/stub_spec.rb +0 -6
- data/spec/rspec/mocks/syntax_spec.rb +19 -0
- data/spec/rspec/mocks/test_double_spec.rb +0 -1
- data/spec/rspec/mocks/verifying_double_spec.rb +281 -18
- data/spec/rspec/mocks/verifying_message_expecation_spec.rb +7 -6
- data/spec/rspec/mocks_spec.rb +168 -42
- data/spec/spec_helper.rb +34 -22
- metadata +94 -63
- metadata.gz.sig +0 -0
- checksums.yaml +0 -15
- checksums.yaml.gz.sig +0 -2
- data/features/outside_rspec/configuration.feature +0 -60
- data/lib/rspec/mocks/arity_calculator.rb +0 -66
- data/lib/rspec/mocks/errors.rb +0 -12
- data/lib/rspec/mocks/mock.rb +0 -7
- data/lib/rspec/mocks/proxy_for_nil.rb +0 -37
- data/lib/rspec/mocks/stub_chain.rb +0 -51
- data/spec/rspec/mocks/argument_expectation_spec.rb +0 -32
- data/spec/rspec/mocks/arity_calculator_spec.rb +0 -95
- data/spec/rspec/mocks/mock_space_spec.rb +0 -113
- data/spec/rspec/mocks/mock_spec.rb +0 -788
@@ -1,6 +1,7 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Mocks
|
3
3
|
module Matchers
|
4
|
+
# @private
|
4
5
|
class ReceiveMessages
|
5
6
|
|
6
7
|
def initialize(message_return_value_hash)
|
@@ -53,11 +54,11 @@ module RSpec
|
|
53
54
|
private
|
54
55
|
|
55
56
|
def proxy_on(subject)
|
56
|
-
::RSpec::Mocks.proxy_for(subject)
|
57
|
+
::RSpec::Mocks.space.proxy_for(subject)
|
57
58
|
end
|
58
59
|
|
59
60
|
def any_instance_of(subject)
|
60
|
-
::RSpec::Mocks.any_instance_recorder_for(subject)
|
61
|
+
::RSpec::Mocks.space.any_instance_recorder_for(subject)
|
61
62
|
end
|
62
63
|
|
63
64
|
def each_message_on(host)
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Mocks
|
3
|
+
# @private
|
4
|
+
class MessageChain
|
5
|
+
attr_reader :object, :chain, :block
|
6
|
+
|
7
|
+
def initialize(object, *chain, &blk)
|
8
|
+
@object = object
|
9
|
+
@chain, @block = format_chain(*chain, &blk)
|
10
|
+
end
|
11
|
+
|
12
|
+
# @api private
|
13
|
+
def setup_chain
|
14
|
+
if chain.length > 1
|
15
|
+
if matching_stub = find_matching_stub
|
16
|
+
chain.shift
|
17
|
+
chain_on(matching_stub.invoke(nil), *chain, &@block)
|
18
|
+
elsif matching_expectation = find_matching_expectation
|
19
|
+
chain.shift
|
20
|
+
chain_on(matching_expectation.invoke_without_incrementing_received_count(nil), *chain, &@block)
|
21
|
+
else
|
22
|
+
next_in_chain = Double.new
|
23
|
+
expectation(object, chain.shift, next_in_chain)
|
24
|
+
chain_on(next_in_chain, *chain, &@block)
|
25
|
+
end
|
26
|
+
else
|
27
|
+
::RSpec::Mocks.allow_message(object, chain.shift, {}, &block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def expectation(object, message, returned_object)
|
34
|
+
raise NotImplementedError.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def chain_on(object, *chain, &block)
|
38
|
+
initialize(object, *chain, &block)
|
39
|
+
setup_chain
|
40
|
+
end
|
41
|
+
|
42
|
+
def format_chain(*chain, &blk)
|
43
|
+
if Hash === chain.last
|
44
|
+
hash = chain.pop
|
45
|
+
hash.each do |k,v|
|
46
|
+
chain << k
|
47
|
+
blk = Proc.new { v }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
return chain.join('.').split('.'), blk
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_matching_stub
|
54
|
+
::RSpec::Mocks.space.proxy_for(object).
|
55
|
+
__send__(:find_matching_method_stub, chain.first.to_sym)
|
56
|
+
end
|
57
|
+
|
58
|
+
def find_matching_expectation
|
59
|
+
::RSpec::Mocks.space.proxy_for(object).
|
60
|
+
__send__(:find_matching_expectation, chain.first.to_sym)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# @private
|
65
|
+
class ExpectChain < MessageChain
|
66
|
+
# @api private
|
67
|
+
def self.expect_chain_on(object, *chain, &blk)
|
68
|
+
new(object, *chain, &blk).setup_chain
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def expectation(object, message, returned_object)
|
74
|
+
::RSpec::Mocks.expect_message(object, message, {}) { returned_object }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# @private
|
79
|
+
class StubChain < MessageChain
|
80
|
+
def self.stub_chain_on(object, *chain, &blk)
|
81
|
+
new(object, *chain, &blk).setup_chain
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def expectation(object, message, returned_object)
|
87
|
+
::RSpec::Mocks.allow_message(object, message, {}) { returned_object }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -8,7 +8,7 @@ module RSpec
|
|
8
8
|
class SimpleMessageExpectation
|
9
9
|
|
10
10
|
def initialize(message, response, error_generator, backtrace_line = nil)
|
11
|
-
@message, @response, @error_generator, @backtrace_line = message, response, error_generator, backtrace_line
|
11
|
+
@message, @response, @error_generator, @backtrace_line = message.to_sym, response, error_generator, backtrace_line
|
12
12
|
@received = false
|
13
13
|
end
|
14
14
|
|
@@ -18,7 +18,7 @@ module RSpec
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def matches?(message, *_)
|
21
|
-
@message == message
|
21
|
+
@message == message.to_sym
|
22
22
|
end
|
23
23
|
|
24
24
|
def called_max_times?
|
@@ -34,6 +34,7 @@ module RSpec
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
+
# @private
|
37
38
|
class MessageExpectation
|
38
39
|
# @private
|
39
40
|
attr_accessor :error_generator, :implementation
|
@@ -76,7 +77,6 @@ module RSpec
|
|
76
77
|
|
77
78
|
# @overload and_return(value)
|
78
79
|
# @overload and_return(first_value, second_value)
|
79
|
-
# @overload and_return(&block)
|
80
80
|
#
|
81
81
|
# Tells the object to return a value when it receives the message. Given
|
82
82
|
# more than one value, the first value is returned the first time the
|
@@ -86,45 +86,33 @@ module RSpec
|
|
86
86
|
# If the message is received more times than there are values, the last
|
87
87
|
# value is received for every subsequent call.
|
88
88
|
#
|
89
|
-
# The block format is still supported, but is unofficially deprecated in
|
90
|
-
# favor of just passing a block to the stub method.
|
91
|
-
#
|
92
89
|
# @example
|
93
90
|
#
|
94
|
-
# counter.
|
91
|
+
# allow(counter).to receive(:count).and_return(1)
|
95
92
|
# counter.count # => 1
|
96
93
|
# counter.count # => 1
|
97
94
|
#
|
98
|
-
# counter.
|
95
|
+
# allow(counter).to receive(:count).and_return(1,2,3)
|
99
96
|
# counter.count # => 1
|
100
97
|
# counter.count # => 2
|
101
98
|
# counter.count # => 3
|
102
99
|
# counter.count # => 3
|
103
100
|
# counter.count # => 3
|
104
101
|
# # etc
|
105
|
-
|
106
|
-
# # Supported, but ...
|
107
|
-
# counter.stub(:count).and_return { 1 }
|
108
|
-
# counter.count # => 1
|
109
|
-
#
|
110
|
-
# # ... this is prefered
|
111
|
-
# counter.stub(:count) { 1 }
|
112
|
-
# counter.count # => 1
|
113
|
-
def and_return(*values, &implementation)
|
102
|
+
def and_return(first_value, *values)
|
114
103
|
if negative?
|
115
104
|
raise "`and_return` is not supported with negative message expectations"
|
116
|
-
|
117
|
-
@expected_received_count = [@expected_received_count, values.size].max unless ignoring_args? || (@expected_received_count == 0 and @at_least)
|
118
|
-
|
119
|
-
if implementation
|
120
|
-
# TODO: deprecate `and_return { value }`
|
121
|
-
self.inner_implementation_action = implementation
|
122
|
-
else
|
123
|
-
self.terminal_implementation_action = AndReturnImplementation.new(values)
|
124
|
-
end
|
105
|
+
end
|
125
106
|
|
126
|
-
|
107
|
+
if block_given?
|
108
|
+
raise ArgumentError, "Implementation blocks aren't supported with `and_return`"
|
127
109
|
end
|
110
|
+
|
111
|
+
values.unshift(first_value)
|
112
|
+
@expected_received_count = [@expected_received_count, values.size].max unless ignoring_args? || (@expected_received_count == 0 and @at_least)
|
113
|
+
self.terminal_implementation_action = AndReturnImplementation.new(values)
|
114
|
+
|
115
|
+
nil
|
128
116
|
end
|
129
117
|
|
130
118
|
def and_yield_receiver_to_implementation
|
@@ -139,21 +127,19 @@ module RSpec
|
|
139
127
|
# Tells the object to delegate to the original unmodified method
|
140
128
|
# when it receives the message.
|
141
129
|
#
|
142
|
-
# @note This is only available on partial
|
130
|
+
# @note This is only available on partial doubles.
|
143
131
|
#
|
144
132
|
# @example
|
145
133
|
#
|
146
|
-
# counter.
|
134
|
+
# expect(counter).to receive(:increment).and_call_original
|
147
135
|
# original_count = counter.count
|
148
136
|
# counter.increment
|
149
137
|
# expect(counter.count).to eq(original_count + 1)
|
150
138
|
def and_call_original
|
151
139
|
if RSpec::Mocks::TestDouble === @method_double.object
|
152
|
-
@error_generator.
|
140
|
+
@error_generator.raise_only_valid_on_a_partial_double(:and_call_original)
|
153
141
|
else
|
154
|
-
if implementation.inner_action
|
155
|
-
RSpec.warning("You're overriding a previous implementation for this stub")
|
156
|
-
end
|
142
|
+
warn_about_stub_override if implementation.inner_action
|
157
143
|
@implementation = AndCallOriginalImplementation.new(@method_double.original_method)
|
158
144
|
@yield_receiver_to_implementation_block = false
|
159
145
|
end
|
@@ -176,10 +162,10 @@ module RSpec
|
|
176
162
|
#
|
177
163
|
# @example
|
178
164
|
#
|
179
|
-
# car.
|
180
|
-
# car.
|
181
|
-
# car.
|
182
|
-
# car.
|
165
|
+
# allow(car).to receive(:go).and_raise
|
166
|
+
# allow(car).to receive(:go).and_raise(OutOfGas)
|
167
|
+
# allow(car).to receive(:go).and_raise(OutOfGas, "At least 2 oz of gas needed to drive")
|
168
|
+
# allow(car).to receive(:go).and_raise(OutOfGas.new(2, :oz))
|
183
169
|
def and_raise(exception = RuntimeError, message = nil)
|
184
170
|
if exception.respond_to?(:exception)
|
185
171
|
exception = message ? exception.exception(message) : exception.exception
|
@@ -197,8 +183,8 @@ module RSpec
|
|
197
183
|
#
|
198
184
|
# @example
|
199
185
|
#
|
200
|
-
# car.
|
201
|
-
# car.
|
186
|
+
# allow(car).to receive(:go).and_throw(:out_of_gas)
|
187
|
+
# allow(car).to receive(:go).and_throw(:out_of_gas, :level => 0.1)
|
202
188
|
def and_throw(*args)
|
203
189
|
self.terminal_implementation_action = Proc.new { throw(*args) }
|
204
190
|
nil
|
@@ -224,29 +210,12 @@ module RSpec
|
|
224
210
|
|
225
211
|
# @private
|
226
212
|
def invoke(parent_stub, *args, &block)
|
227
|
-
|
228
|
-
|
229
|
-
end
|
230
|
-
|
231
|
-
if negative? || ((@exactly || @at_most) && (@actual_received_count == @expected_received_count))
|
232
|
-
@actual_received_count += 1
|
233
|
-
@failed_fast = true
|
234
|
-
#args are the args we actually received, @argument_list_matcher is the
|
235
|
-
#list of args we were expecting
|
236
|
-
@error_generator.raise_expectation_error(@message, @expected_received_count, @argument_list_matcher, @actual_received_count, expectation_count_type, *args)
|
237
|
-
end
|
238
|
-
|
239
|
-
@order_group.handle_order_constraint self
|
213
|
+
invoke_incrementing_actual_calls_by(1, parent_stub, *args, &block)
|
214
|
+
end
|
240
215
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
elsif parent_stub
|
245
|
-
parent_stub.invoke(nil, *args, &block)
|
246
|
-
end
|
247
|
-
ensure
|
248
|
-
@actual_received_count += 1
|
249
|
-
end
|
216
|
+
# @private
|
217
|
+
def invoke_without_incrementing_received_count(parent_stub, *args, &block)
|
218
|
+
invoke_incrementing_actual_calls_by(0, parent_stub, *args, &block)
|
250
219
|
end
|
251
220
|
|
252
221
|
# @private
|
@@ -350,14 +319,14 @@ module RSpec
|
|
350
319
|
#
|
351
320
|
# @example
|
352
321
|
#
|
353
|
-
# cart.
|
354
|
-
# cart.
|
322
|
+
# allow(cart).to receive(:add) { :failure }
|
323
|
+
# allow(cart).to receive(:add).with(Book.new(:isbn => 1934356379)) { :success }
|
355
324
|
# cart.add(Book.new(:isbn => 1234567890))
|
356
325
|
# # => :failure
|
357
326
|
# cart.add(Book.new(:isbn => 1934356379))
|
358
327
|
# # => :success
|
359
328
|
#
|
360
|
-
# cart.
|
329
|
+
# expect(cart).to receive(:add).with(Book.new(:isbn => 1934356379)) { :success }
|
361
330
|
# cart.add(Book.new(:isbn => 1234567890))
|
362
331
|
# # => failed expectation
|
363
332
|
# cart.add(Book.new(:isbn => 1934356379))
|
@@ -378,7 +347,7 @@ module RSpec
|
|
378
347
|
#
|
379
348
|
# @example
|
380
349
|
#
|
381
|
-
# dealer.
|
350
|
+
# expect(dealer).to receive(:deal_card).exactly(10).times
|
382
351
|
def exactly(n, &block)
|
383
352
|
self.inner_implementation_action = block
|
384
353
|
set_expected_received_count :exactly, n
|
@@ -390,7 +359,7 @@ module RSpec
|
|
390
359
|
#
|
391
360
|
# @example
|
392
361
|
#
|
393
|
-
# dealer.
|
362
|
+
# expect(dealer).to receive(:deal_card).at_least(9).times
|
394
363
|
def at_least(n, &block)
|
395
364
|
set_expected_received_count :at_least, n
|
396
365
|
|
@@ -408,7 +377,7 @@ module RSpec
|
|
408
377
|
#
|
409
378
|
# @example
|
410
379
|
#
|
411
|
-
# dealer.
|
380
|
+
# expect(dealer).to receive(:deal_card).at_most(10).times
|
412
381
|
def at_most(n, &block)
|
413
382
|
self.inner_implementation_action = block
|
414
383
|
set_expected_received_count :at_most, n
|
@@ -419,9 +388,9 @@ module RSpec
|
|
419
388
|
#
|
420
389
|
# @example
|
421
390
|
#
|
422
|
-
# dealer.
|
423
|
-
# dealer.
|
424
|
-
# dealer.
|
391
|
+
# expect(dealer).to receive(:deal_card).exactly(10).times
|
392
|
+
# expect(dealer).to receive(:deal_card).at_least(10).times
|
393
|
+
# expect(dealer).to receive(:deal_card).at_most(10).times
|
425
394
|
def times(&block)
|
426
395
|
self.inner_implementation_action = block
|
427
396
|
self
|
@@ -431,7 +400,7 @@ module RSpec
|
|
431
400
|
#
|
432
401
|
# @example
|
433
402
|
#
|
434
|
-
# car.
|
403
|
+
# expect(car).to receive(:stop).never
|
435
404
|
def never
|
436
405
|
ErrorGenerator.raise_double_negation_error("expect(obj)") if negative?
|
437
406
|
@expected_received_count = 0
|
@@ -442,7 +411,7 @@ module RSpec
|
|
442
411
|
#
|
443
412
|
# @example
|
444
413
|
#
|
445
|
-
# car.
|
414
|
+
# expect(car).to receive(:go).once
|
446
415
|
def once(&block)
|
447
416
|
self.inner_implementation_action = block
|
448
417
|
set_expected_received_count :exactly, 1
|
@@ -453,7 +422,7 @@ module RSpec
|
|
453
422
|
#
|
454
423
|
# @example
|
455
424
|
#
|
456
|
-
# car.
|
425
|
+
# expect(car).to receive(:go).twice
|
457
426
|
def twice(&block)
|
458
427
|
self.inner_implementation_action = block
|
459
428
|
set_expected_received_count :exactly, 2
|
@@ -464,9 +433,9 @@ module RSpec
|
|
464
433
|
#
|
465
434
|
# @example
|
466
435
|
#
|
467
|
-
# api.
|
468
|
-
# api.
|
469
|
-
# api.
|
436
|
+
# expect(api).to receive(:prepare).ordered
|
437
|
+
# expect(api).to receive(:run).ordered
|
438
|
+
# expect(api).to receive(:finish).ordered
|
470
439
|
def ordered(&block)
|
471
440
|
self.inner_implementation_action = block
|
472
441
|
@ordered = true
|
@@ -495,6 +464,32 @@ module RSpec
|
|
495
464
|
|
496
465
|
private
|
497
466
|
|
467
|
+
def invoke_incrementing_actual_calls_by(increment, parent_stub, *args, &block)
|
468
|
+
if yield_receiver_to_implementation_block?
|
469
|
+
args.unshift(orig_object)
|
470
|
+
end
|
471
|
+
|
472
|
+
if negative? || ((@exactly || @at_most) && (@actual_received_count == @expected_received_count))
|
473
|
+
@actual_received_count += increment
|
474
|
+
@failed_fast = true
|
475
|
+
#args are the args we actually received, @argument_list_matcher is the
|
476
|
+
#list of args we were expecting
|
477
|
+
@error_generator.raise_expectation_error(@message, @expected_received_count, @argument_list_matcher, @actual_received_count, expectation_count_type, *args)
|
478
|
+
end
|
479
|
+
|
480
|
+
@order_group.handle_order_constraint self
|
481
|
+
|
482
|
+
begin
|
483
|
+
if implementation.present?
|
484
|
+
implementation.call(*args, &block)
|
485
|
+
elsif parent_stub
|
486
|
+
parent_stub.invoke(nil, *args, &block)
|
487
|
+
end
|
488
|
+
ensure
|
489
|
+
@actual_received_count += increment
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
498
493
|
def failed_fast?
|
499
494
|
@failed_fast
|
500
495
|
end
|
@@ -515,13 +510,21 @@ module RSpec
|
|
515
510
|
end
|
516
511
|
|
517
512
|
def inner_implementation_action=(action)
|
518
|
-
|
519
|
-
implementation.inner_action
|
513
|
+
return unless action
|
514
|
+
warn_about_stub_override if implementation.inner_action
|
515
|
+
implementation.inner_action = action
|
520
516
|
end
|
521
517
|
|
522
518
|
def terminal_implementation_action=(action)
|
523
519
|
implementation.terminal_action = action
|
524
520
|
end
|
521
|
+
|
522
|
+
def warn_about_stub_override
|
523
|
+
RSpec.warning(
|
524
|
+
"You're overriding a previous stub implementation of `#{@message}`. " +
|
525
|
+
"Called from #{CallerFilter.first_non_rspec_line}."
|
526
|
+
)
|
527
|
+
end
|
525
528
|
end
|
526
529
|
|
527
530
|
# Handles the implementation of an `and_yield` declaration.
|
@@ -538,10 +541,13 @@ module RSpec
|
|
538
541
|
|
539
542
|
@error_generator.raise_missing_block_error @args_to_yield unless block
|
540
543
|
value = nil
|
544
|
+
block_signature = BlockSignature.new(block)
|
545
|
+
|
541
546
|
@args_to_yield.each do |args|
|
542
|
-
|
543
|
-
@error_generator.raise_wrong_arity_error
|
547
|
+
unless MethodSignatureVerifier.new(block_signature, args).valid?
|
548
|
+
@error_generator.raise_wrong_arity_error(args, block_signature)
|
544
549
|
end
|
550
|
+
|
545
551
|
value = @eval_context ? @eval_context.instance_exec(*args, &block) : block.call(*args)
|
546
552
|
end
|
547
553
|
value
|