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.
Files changed (114) hide show
  1. data.tar.gz.sig +1 -1
  2. data/Changelog.md +95 -3
  3. data/README.md +27 -13
  4. data/features/README.md +15 -7
  5. data/features/argument_matchers/README.md +5 -5
  6. data/features/argument_matchers/explicit.feature +6 -6
  7. data/features/argument_matchers/general_matchers.feature +4 -4
  8. data/features/argument_matchers/type_matchers.feature +2 -2
  9. data/features/message_expectations/README.md +29 -27
  10. data/features/message_expectations/call_original.feature +0 -1
  11. data/features/message_expectations/message_chains_using_expect.feature +49 -0
  12. data/features/method_stubs/README.md +2 -1
  13. data/features/method_stubs/{any_instance.feature → allow_any_instance_of.feature} +12 -12
  14. data/features/method_stubs/{stub_chain.feature → receive_message_chain.feature} +3 -3
  15. data/features/method_stubs/to_ary.feature +1 -1
  16. data/features/mutating_constants/stub_defined_constant.feature +0 -1
  17. data/features/outside_rspec/standalone.feature +1 -1
  18. data/features/spies/spy_pure_mock_method.feature +1 -1
  19. data/features/test_frameworks/test_unit.feature +21 -10
  20. data/features/verifying_doubles/README.md +17 -0
  21. data/features/verifying_doubles/class_doubles.feature +1 -16
  22. data/features/verifying_doubles/dynamic_classes.feature +0 -1
  23. data/features/verifying_doubles/{introduction.feature → instance_doubles.feature} +41 -23
  24. data/features/verifying_doubles/partial_doubles.feature +2 -2
  25. data/lib/rspec/mocks.rb +69 -82
  26. data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +35 -0
  27. data/lib/rspec/mocks/any_instance/expectation_chain.rb +1 -2
  28. data/lib/rspec/mocks/any_instance/recorder.rb +52 -18
  29. data/lib/rspec/mocks/any_instance/stub_chain.rb +1 -1
  30. data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +4 -0
  31. data/lib/rspec/mocks/argument_list_matcher.rb +10 -44
  32. data/lib/rspec/mocks/argument_matchers.rb +132 -163
  33. data/lib/rspec/mocks/configuration.rb +28 -4
  34. data/lib/rspec/mocks/error_generator.rb +46 -13
  35. data/lib/rspec/mocks/example_methods.rb +13 -12
  36. data/lib/rspec/mocks/extensions/marshal.rb +1 -1
  37. data/lib/rspec/mocks/framework.rb +3 -4
  38. data/lib/rspec/mocks/instance_method_stasher.rb +2 -3
  39. data/lib/rspec/mocks/matchers/have_received.rb +8 -6
  40. data/lib/rspec/mocks/matchers/receive.rb +28 -20
  41. data/lib/rspec/mocks/matchers/receive_message_chain.rb +65 -0
  42. data/lib/rspec/mocks/matchers/receive_messages.rb +3 -2
  43. data/lib/rspec/mocks/message_chain.rb +91 -0
  44. data/lib/rspec/mocks/message_expectation.rb +86 -80
  45. data/lib/rspec/mocks/method_double.rb +2 -11
  46. data/lib/rspec/mocks/method_reference.rb +82 -23
  47. data/lib/rspec/mocks/method_signature_verifier.rb +207 -0
  48. data/lib/rspec/mocks/mutate_const.rb +34 -50
  49. data/lib/rspec/mocks/object_reference.rb +0 -1
  50. data/lib/rspec/mocks/proxy.rb +70 -13
  51. data/lib/rspec/mocks/ruby_features.rb +24 -0
  52. data/lib/rspec/mocks/space.rb +105 -31
  53. data/lib/rspec/mocks/standalone.rb +2 -2
  54. data/lib/rspec/mocks/syntax.rb +43 -8
  55. data/lib/rspec/mocks/targets.rb +16 -7
  56. data/lib/rspec/mocks/test_double.rb +41 -15
  57. data/lib/rspec/mocks/verifying_double.rb +51 -4
  58. data/lib/rspec/mocks/verifying_message_expecation.rb +12 -12
  59. data/lib/rspec/mocks/verifying_proxy.rb +32 -19
  60. data/lib/rspec/mocks/version.rb +1 -1
  61. data/spec/rspec/mocks/and_call_original_spec.rb +28 -7
  62. data/spec/rspec/mocks/and_return_spec.rb +23 -0
  63. data/spec/rspec/mocks/and_yield_spec.rb +1 -2
  64. data/spec/rspec/mocks/any_instance_spec.rb +33 -17
  65. data/spec/rspec/mocks/array_including_matcher_spec.rb +6 -6
  66. data/spec/rspec/mocks/before_all_spec.rb +132 -0
  67. data/spec/rspec/mocks/block_return_value_spec.rb +12 -1
  68. data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +9 -11
  69. data/spec/rspec/mocks/configuration_spec.rb +14 -1
  70. data/spec/rspec/mocks/double_spec.rb +867 -24
  71. data/spec/rspec/mocks/example_methods_spec.rb +13 -0
  72. data/spec/rspec/mocks/extensions/marshal_spec.rb +17 -17
  73. data/spec/rspec/mocks/failing_argument_matchers_spec.rb +29 -1
  74. data/spec/rspec/mocks/hash_excluding_matcher_spec.rb +12 -12
  75. data/spec/rspec/mocks/hash_including_matcher_spec.rb +21 -17
  76. data/spec/rspec/mocks/instance_method_stasher_spec.rb +2 -3
  77. data/spec/rspec/mocks/matchers/have_received_spec.rb +7 -0
  78. data/spec/rspec/mocks/matchers/receive_message_chain_spec.rb +198 -0
  79. data/spec/rspec/mocks/matchers/receive_messages_spec.rb +2 -2
  80. data/spec/rspec/mocks/matchers/receive_spec.rb +19 -6
  81. data/spec/rspec/mocks/method_signature_verifier_spec.rb +272 -0
  82. data/spec/rspec/mocks/methods_spec.rb +0 -1
  83. data/spec/rspec/mocks/multiple_return_value_spec.rb +2 -2
  84. data/spec/rspec/mocks/mutate_const_spec.rb +24 -1
  85. data/spec/rspec/mocks/nil_expectation_warning_spec.rb +6 -22
  86. data/spec/rspec/mocks/null_object_mock_spec.rb +13 -7
  87. data/spec/rspec/mocks/options_hash_spec.rb +3 -3
  88. data/spec/rspec/mocks/{partial_mock_spec.rb → partial_double_spec.rb} +5 -2
  89. data/spec/rspec/mocks/{partial_mock_using_mocks_directly_spec.rb → partial_double_using_mocks_directly_spec.rb} +1 -1
  90. data/spec/rspec/mocks/passing_argument_matchers_spec.rb +18 -0
  91. data/spec/rspec/mocks/serialization_spec.rb +1 -0
  92. data/spec/rspec/mocks/space_spec.rb +218 -7
  93. data/spec/rspec/mocks/stub_chain_spec.rb +6 -0
  94. data/spec/rspec/mocks/stub_spec.rb +0 -6
  95. data/spec/rspec/mocks/syntax_spec.rb +19 -0
  96. data/spec/rspec/mocks/test_double_spec.rb +0 -1
  97. data/spec/rspec/mocks/verifying_double_spec.rb +281 -18
  98. data/spec/rspec/mocks/verifying_message_expecation_spec.rb +7 -6
  99. data/spec/rspec/mocks_spec.rb +168 -42
  100. data/spec/spec_helper.rb +34 -22
  101. metadata +94 -63
  102. metadata.gz.sig +0 -0
  103. checksums.yaml +0 -15
  104. checksums.yaml.gz.sig +0 -2
  105. data/features/outside_rspec/configuration.feature +0 -60
  106. data/lib/rspec/mocks/arity_calculator.rb +0 -66
  107. data/lib/rspec/mocks/errors.rb +0 -12
  108. data/lib/rspec/mocks/mock.rb +0 -7
  109. data/lib/rspec/mocks/proxy_for_nil.rb +0 -37
  110. data/lib/rspec/mocks/stub_chain.rb +0 -51
  111. data/spec/rspec/mocks/argument_expectation_spec.rb +0 -32
  112. data/spec/rspec/mocks/arity_calculator_spec.rb +0 -95
  113. data/spec/rspec/mocks/mock_space_spec.rb +0 -113
  114. 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.stub(:count).and_return(1)
91
+ # allow(counter).to receive(:count).and_return(1)
95
92
  # counter.count # => 1
96
93
  # counter.count # => 1
97
94
  #
98
- # counter.stub(:count).and_return(1,2,3)
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
- else
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
- nil
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 mock objects.
130
+ # @note This is only available on partial doubles.
143
131
  #
144
132
  # @example
145
133
  #
146
- # counter.should_receive(:increment).and_call_original
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.raise_only_valid_on_a_partial_mock(:and_call_original)
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.stub(:go).and_raise
180
- # car.stub(:go).and_raise(OutOfGas)
181
- # car.stub(:go).and_raise(OutOfGas, "At least 2 oz of gas needed to drive")
182
- # car.stub(:go).and_raise(OutOfGas.new(2, :oz))
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.stub(:go).and_throw(:out_of_gas)
201
- # car.stub(:go).and_throw(:out_of_gas, :level => 0.1)
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
- if yield_receiver_to_implementation_block?
228
- args.unshift(orig_object)
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
- begin
242
- if implementation.present?
243
- implementation.call(*args, &block)
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.stub(:add) { :failure }
354
- # cart.stub(:add).with(Book.new(:isbn => 1934356379)) { :success }
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.should_receive(:add).with(Book.new(:isbn => 1934356379)) { :success }
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.should_receive(:deal_card).exactly(10).times
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.should_receive(:deal_card).at_least(9).times
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.should_receive(:deal_card).at_most(10).times
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.should_receive(:deal_card).exactly(10).times
423
- # dealer.should_receive(:deal_card).at_least(10).times
424
- # dealer.should_receive(:deal_card).at_most(10).times
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.should_receive(:stop).never
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.should_receive(:go).once
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.should_receive(:go).twice
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.should_receive(:prepare).ordered
468
- # api.should_receive(:run).ordered
469
- # api.should_receive(:finish).ordered
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
- RSpec.warning("You're overriding a previous implementation for this stub") if implementation.inner_action
519
- implementation.inner_action = action if 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
- if block.arity > -1 && args.length != block.arity
543
- @error_generator.raise_wrong_arity_error args, block.arity
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