rspec-mocks 3.0.0.beta1 → 3.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
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