mocha 1.10.0 → 1.11.2

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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.yardopts +1 -0
  4. data/RELEASE.md +49 -0
  5. data/Rakefile +1 -4
  6. data/docs/Mocha.html +2 -2
  7. data/docs/Mocha/API.html +167 -35
  8. data/docs/Mocha/ClassMethods.html +2 -2
  9. data/docs/Mocha/Configuration.html +197 -55
  10. data/docs/Mocha/Expectation.html +284 -76
  11. data/docs/Mocha/ExpectationError.html +2 -2
  12. data/docs/Mocha/ExpectationErrorFactory.html +2 -2
  13. data/docs/Mocha/Hooks.html +2 -2
  14. data/docs/Mocha/Integration.html +2 -2
  15. data/docs/Mocha/Integration/MiniTest.html +2 -2
  16. data/docs/Mocha/Integration/MiniTest/Adapter.html +2 -2
  17. data/docs/Mocha/Integration/TestUnit.html +2 -2
  18. data/docs/Mocha/Integration/TestUnit/Adapter.html +2 -2
  19. data/docs/Mocha/Mock.html +14 -41
  20. data/docs/Mocha/ObjectMethods.html +2 -2
  21. data/docs/Mocha/ParameterMatchers.html +14 -26
  22. data/docs/Mocha/ParameterMatchers/AllOf.html +2 -2
  23. data/docs/Mocha/ParameterMatchers/AnyOf.html +2 -2
  24. data/docs/Mocha/ParameterMatchers/AnyParameters.html +2 -2
  25. data/docs/Mocha/ParameterMatchers/Anything.html +2 -2
  26. data/docs/Mocha/ParameterMatchers/Base.html +2 -2
  27. data/docs/Mocha/ParameterMatchers/Equals.html +2 -2
  28. data/docs/Mocha/ParameterMatchers/EquivalentUri.html +2 -2
  29. data/docs/Mocha/ParameterMatchers/HasEntries.html +2 -2
  30. data/docs/Mocha/ParameterMatchers/HasEntry.html +2 -2
  31. data/docs/Mocha/ParameterMatchers/HasKey.html +2 -2
  32. data/docs/Mocha/ParameterMatchers/HasValue.html +2 -2
  33. data/docs/Mocha/ParameterMatchers/Includes.html +2 -2
  34. data/docs/Mocha/ParameterMatchers/InstanceOf.html +2 -2
  35. data/docs/Mocha/ParameterMatchers/IsA.html +2 -2
  36. data/docs/Mocha/ParameterMatchers/KindOf.html +2 -2
  37. data/docs/Mocha/ParameterMatchers/Not.html +2 -2
  38. data/docs/Mocha/ParameterMatchers/Optionally.html +2 -2
  39. data/docs/Mocha/ParameterMatchers/RegexpMatches.html +2 -2
  40. data/docs/Mocha/ParameterMatchers/RespondsWith.html +2 -2
  41. data/docs/Mocha/ParameterMatchers/YamlEquivalent.html +2 -2
  42. data/docs/Mocha/Sequence.html +2 -2
  43. data/docs/Mocha/StateMachine.html +5 -5
  44. data/docs/Mocha/StateMachine/State.html +2 -2
  45. data/docs/Mocha/StateMachine/StatePredicate.html +2 -2
  46. data/docs/Mocha/StubbingError.html +2 -2
  47. data/docs/_index.html +3 -3
  48. data/docs/file.COPYING.html +2 -2
  49. data/docs/file.MIT-LICENSE.html +2 -2
  50. data/docs/file.README.html +2 -2
  51. data/docs/file.RELEASE.html +74 -2
  52. data/docs/frames.html +1 -1
  53. data/docs/index.html +2 -2
  54. data/docs/method_list.html +51 -27
  55. data/docs/top-level-namespace.html +2 -2
  56. data/lib/mocha/api.rb +83 -19
  57. data/lib/mocha/block_matcher.rb +31 -0
  58. data/lib/mocha/configuration.rb +57 -1
  59. data/lib/mocha/deprecation.rb +2 -1
  60. data/lib/mocha/expectation.rb +48 -7
  61. data/lib/mocha/invocation.rb +20 -4
  62. data/lib/mocha/mock.rb +42 -16
  63. data/lib/mocha/mockery.rb +14 -14
  64. data/lib/mocha/parameter_matchers/has_entries.rb +2 -3
  65. data/lib/mocha/parameter_matchers/has_entry.rb +2 -3
  66. data/lib/mocha/parameter_matchers/has_key.rb +2 -3
  67. data/lib/mocha/parameter_matchers/has_value.rb +2 -3
  68. data/lib/mocha/parameter_matchers/is_a.rb +2 -3
  69. data/lib/mocha/parameter_matchers/not.rb +2 -3
  70. data/lib/mocha/state_machine.rb +2 -3
  71. data/lib/mocha/stubbed_method.rb +4 -6
  72. data/lib/mocha/version.rb +1 -1
  73. data/lib/mocha/yield_parameters.rb +5 -11
  74. data/test/acceptance/acceptance_test_helper.rb +1 -0
  75. data/test/acceptance/display_matching_invocations_alongside_expectations_test.rb +5 -5
  76. data/test/acceptance/failure_messages_test.rb +16 -0
  77. data/test/acceptance/issue_457_test.rb +31 -0
  78. data/test/acceptance/mocha_example_test.rb +11 -1
  79. data/test/acceptance/mock_built_with_first_argument_type_being_string_test.rb +98 -0
  80. data/test/acceptance/mock_test.rb +64 -12
  81. data/test/acceptance/multiple_yielding_test.rb +59 -0
  82. data/test/acceptance/stubba_example_test.rb +11 -1
  83. data/test/acceptance/stubbing_non_existent_any_instance_method_test.rb +16 -0
  84. data/test/acceptance/yielding_test.rb +80 -0
  85. data/test/unit/expectation_test.rb +30 -3
  86. data/test/unit/yield_parameters_test.rb +35 -53
  87. metadata +8 -9
  88. data/lib/mocha/multiple_yields.rb +0 -15
  89. data/lib/mocha/no_yields.rb +0 -5
  90. data/lib/mocha/pretty_parameters.rb +0 -24
  91. data/lib/mocha/single_yield.rb +0 -13
  92. data/test/unit/multiple_yields_test.rb +0 -16
  93. data/test/unit/no_yields_test.rb +0 -16
  94. data/test/unit/single_yield_test.rb +0 -16
@@ -0,0 +1,31 @@
1
+ module Mocha
2
+ module BlockMatchers
3
+ class OptionalBlock
4
+ def match?(_actual_block)
5
+ true
6
+ end
7
+
8
+ def mocha_inspect; end
9
+ end
10
+
11
+ class BlockGiven
12
+ def match?(actual_block)
13
+ !actual_block.nil?
14
+ end
15
+
16
+ def mocha_inspect
17
+ 'with block given'
18
+ end
19
+ end
20
+
21
+ class NoBlockGiven
22
+ def match?(actual_block)
23
+ actual_block.nil?
24
+ end
25
+
26
+ def mocha_inspect
27
+ 'with no block given'
28
+ end
29
+ end
30
+ end
31
+ end
@@ -42,7 +42,8 @@ module Mocha
42
42
  :stubbing_non_existent_method => :allow,
43
43
  :stubbing_non_public_method => :allow,
44
44
  :stubbing_method_on_nil => :prevent,
45
- :display_matching_invocations_on_failure => false
45
+ :display_matching_invocations_on_failure => false,
46
+ :reinstate_undocumented_behaviour_from_v1_9 => true
46
47
  }.freeze
47
48
 
48
49
  attr_reader :options
@@ -247,6 +248,61 @@ module Mocha
247
248
  @options[:display_matching_invocations_on_failure]
248
249
  end
249
250
 
251
+ # Reinstate undocumented behaviour from v1.9
252
+ #
253
+ # Previously when {API#mock}, {API#stub}, or {API#stub_everything} were called with the first argument being a symbol, they built an *unnamed* mock object *and* expected or stubbed the method identified by the symbol argument; subsequent arguments were ignored.
254
+ # Now these methods build a *named* mock with the name specified by the symbol argument; *no* methods are expected or stubbed and subsequent arguments *are* taken into account.
255
+ #
256
+ # Previously if {Expectation#yields} or {Expectation#multiple_yields} was called on an expectation, but no block was given when the method was invoked, the instruction to yield was ignored.
257
+ # Now a +LocalJumpError+ is raised.
258
+ #
259
+ # Enabling this configuration option reinstates the previous behaviour, but displays a deprecation warning.
260
+ #
261
+ # @param [Boolean] value +true+ to reinstate undocumented behaviour; enabled by default.
262
+ #
263
+ # @example Reinstate undocumented behaviour for {API#mock}
264
+ # Mocha.configure do |c|
265
+ # c.reinstate_undocumented_behaviour_from_v1_9 = true
266
+ # end
267
+ #
268
+ # foo = mock(:bar)
269
+ # foo.inspect # => #<Mock>
270
+ #
271
+ # not all expectations were satisfied
272
+ # unsatisfied expectations:
273
+ # - expected exactly once, invoked never: #<Mock>.foo
274
+ #
275
+ # @example Reinstate undocumented behaviour for {API#stub}
276
+ # Mocha.configure do |c|
277
+ # c.reinstate_undocumented_behaviour_from_v1_9 = true
278
+ # end
279
+ #
280
+ # foo = stub(:bar)
281
+ # foo.inspect # => #<Mock>
282
+ # foo.bar # => nil
283
+ #
284
+ # @example Reinstate undocumented behaviour for {Expectation#yields}
285
+ # foo = mock('foo')
286
+ # foo.stubs(:my_method).yields(1, 2)
287
+ # foo.my_method # => raises LocalJumpError when no block is supplied
288
+ #
289
+ # Mocha.configure do |c|
290
+ # c.reinstate_undocumented_behaviour_from_v1_9 = true
291
+ # end
292
+ #
293
+ # foo = mock('foo')
294
+ # foo.stubs(:my_method).yields(1, 2)
295
+ # foo.my_method # => does *not* raise LocalJumpError when no block is supplied
296
+ #
297
+ def reinstate_undocumented_behaviour_from_v1_9=(value)
298
+ @options[:reinstate_undocumented_behaviour_from_v1_9] = value
299
+ end
300
+
301
+ # @private
302
+ def reinstate_undocumented_behaviour_from_v1_9?
303
+ @options[:reinstate_undocumented_behaviour_from_v1_9]
304
+ end
305
+
250
306
  class << self
251
307
  # Allow the specified +action+.
252
308
  #
@@ -5,7 +5,8 @@ module Mocha
5
5
  class << self
6
6
  attr_accessor :mode, :messages
7
7
 
8
- def warning(message)
8
+ def warning(*messages)
9
+ message = messages.join
9
10
  @messages << message
10
11
  return if mode == :disabled
11
12
  filter = BacktraceFilter.new
@@ -10,6 +10,7 @@ require 'mocha/in_state_ordering_constraint'
10
10
  require 'mocha/change_state_side_effect'
11
11
  require 'mocha/cardinality'
12
12
  require 'mocha/configuration'
13
+ require 'mocha/block_matcher'
13
14
 
14
15
  module Mocha
15
16
  # Methods on expectations returned from {Mock#expects}, {Mock#stubs}, {ObjectMethods#expects} and {ObjectMethods#stubs}.
@@ -224,6 +225,44 @@ module Mocha
224
225
  self
225
226
  end
226
227
 
228
+ # Modifies expectation so that the expected method must be called with a block.
229
+ #
230
+ # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
231
+ #
232
+ # @example Expected method must be called with a block.
233
+ # object = mock()
234
+ # object.expects(:expected_method).with_block_given
235
+ # object.expected_method { 1 + 1 }
236
+ # # => verify succeeds
237
+ #
238
+ # object = mock()
239
+ # object.expects(:expected_method).with_block_given
240
+ # object.expected_method
241
+ # # => verify fails
242
+ def with_block_given
243
+ @block_matcher = BlockMatchers::BlockGiven.new
244
+ self
245
+ end
246
+
247
+ # Modifies expectation so that the expected method must be called without a block.
248
+ #
249
+ # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
250
+ #
251
+ # @example Expected method must be called without a block.
252
+ # object = mock()
253
+ # object.expects(:expected_method).with_no_block_given
254
+ # object.expected_method
255
+ # # => verify succeeds
256
+ #
257
+ # object = mock()
258
+ # object.expects(:expected_method).with_block_given
259
+ # object.expected_method { 1 + 1 }
260
+ # # => verify fails
261
+ def with_no_block_given
262
+ @block_matcher = BlockMatchers::NoBlockGiven.new
263
+ self
264
+ end
265
+
227
266
  # Modifies expectation so that when the expected method is called, it yields with the specified +parameters+ (even if no block is provided, in which case yielding will result in a +LocalJumpError+).
228
267
  #
229
268
  # May be called multiple times on the same expectation for consecutive invocations.
@@ -256,13 +295,12 @@ module Mocha
256
295
  # fibonacci.next_pair { |first, second| sum = first + second }
257
296
  # sum # => 2
258
297
  def yields(*parameters)
259
- @yield_parameters.add(*parameters)
260
- self
298
+ multiple_yields(parameters)
261
299
  end
262
300
 
263
301
  # Modifies expectation so that when the expected method is called, it yields multiple times per invocation with the specified +parameter_groups+ (even if no block is provided, in which case yielding will result in a +LocalJumpError+).
264
302
  #
265
- # @param [*Array<Array>] parameter_groups each element of +parameter_groups+ should iself be an +Array+ representing the parameters to be passed to the block for a single yield.
303
+ # @param [*Array<Array>] parameter_groups each element of +parameter_groups+ should iself be an +Array+ representing the parameters to be passed to the block for a single yield. Any element of +parameter_groups+ that is not an +Array+ is wrapped in an +Array+.
266
304
  # @return [Expectation] the same expectation, thereby allowing invocations of other {Expectation} methods to be chained.
267
305
  # @see #then
268
306
  #
@@ -283,7 +321,7 @@ module Mocha
283
321
  # rows_from_first_invocation # => [['old_row1_col1', 'old_row1_col2'], ['old_row2_col1', '']]
284
322
  # rows_from_second_invocation # => [['new_row1_col1', ''], ['new_row2_col1', 'new_row2_col2']]
285
323
  def multiple_yields(*parameter_groups)
286
- @yield_parameters.multiple_add(*parameter_groups)
324
+ @yield_parameters.add(*parameter_groups)
287
325
  self
288
326
  end
289
327
 
@@ -511,6 +549,7 @@ module Mocha
511
549
  @mock = mock
512
550
  @method_matcher = MethodMatcher.new(expected_method_name.to_sym)
513
551
  @parameters_matcher = ParametersMatcher.new
552
+ @block_matcher = BlockMatchers::OptionalBlock.new
514
553
  @ordering_constraints = []
515
554
  @side_effects = []
516
555
  @cardinality = Cardinality.exactly(1)
@@ -551,7 +590,7 @@ module Mocha
551
590
 
552
591
  # @private
553
592
  def match?(invocation)
554
- @method_matcher.match?(invocation.method_name) && @parameters_matcher.match?(invocation.arguments) && in_correct_order?
593
+ @method_matcher.match?(invocation.method_name) && @parameters_matcher.match?(invocation.arguments) && @block_matcher.match?(invocation.block) && in_correct_order?
555
594
  end
556
595
 
557
596
  # @private
@@ -568,7 +607,7 @@ module Mocha
568
607
  def invoke(invocation)
569
608
  perform_side_effects
570
609
  @cardinality << invocation
571
- invocation.call(@yield_parameters, @return_values) { |*yield_args| yield(*yield_args) }
610
+ invocation.call(@yield_parameters, @return_values)
572
611
  end
573
612
 
574
613
  # @private
@@ -601,7 +640,9 @@ module Mocha
601
640
 
602
641
  # @private
603
642
  def method_signature
604
- "#{@mock.mocha_inspect}.#{@method_matcher.mocha_inspect}#{@parameters_matcher.mocha_inspect}"
643
+ signature = "#{@mock.mocha_inspect}.#{@method_matcher.mocha_inspect}#{@parameters_matcher.mocha_inspect}"
644
+ signature << " #{@block_matcher.mocha_inspect}" if @block_matcher.mocha_inspect
645
+ signature
605
646
  end
606
647
  end
607
648
  end
@@ -3,15 +3,18 @@ require 'mocha/raised_exception'
3
3
  require 'mocha/return_values'
4
4
  require 'mocha/thrown_object'
5
5
  require 'mocha/yield_parameters'
6
+ require 'mocha/configuration'
7
+ require 'mocha/deprecation'
6
8
 
7
9
  module Mocha
8
10
  class Invocation
9
- attr_reader :method_name
11
+ attr_reader :method_name, :block
10
12
 
11
- def initialize(mock, method_name, *arguments)
13
+ def initialize(mock, method_name, *arguments, &block)
12
14
  @mock = mock
13
15
  @method_name = method_name
14
16
  @arguments = arguments
17
+ @block = block
15
18
  @yields = []
16
19
  @result = nil
17
20
  end
@@ -19,7 +22,18 @@ module Mocha
19
22
  def call(yield_parameters = YieldParameters.new, return_values = ReturnValues.new)
20
23
  yield_parameters.next_invocation.each do |yield_args|
21
24
  @yields << ParametersMatcher.new(yield_args)
22
- yield(*yield_args)
25
+ if @block
26
+ @block.call(*yield_args)
27
+ else
28
+ raise LocalJumpError unless Mocha.configuration.reinstate_undocumented_behaviour_from_v1_9?
29
+ yield_args_description = ParametersMatcher.new(yield_args).mocha_inspect
30
+ Deprecation.warning(
31
+ "Stubbed method was instructed to yield #{yield_args_description}, but no block was given by invocation: #{call_description}.",
32
+ ' This will raise a LocalJumpError in the future.',
33
+ ' Use Expectation#with_block_given to constrain this expectation to match invocations supplying a block.',
34
+ ' And, if necessary, add another expectation to match invocations not supplying a block.'
35
+ )
36
+ end
23
37
  end
24
38
  return_values.next(self)
25
39
  end
@@ -41,7 +55,9 @@ module Mocha
41
55
  end
42
56
 
43
57
  def call_description
44
- "#{@mock.mocha_inspect}.#{@method_name}#{ParametersMatcher.new(@arguments).mocha_inspect}"
58
+ description = "#{@mock.mocha_inspect}.#{@method_name}#{ParametersMatcher.new(@arguments).mocha_inspect}"
59
+ description << ' { ... }' unless @block.nil?
60
+ description
45
61
  end
46
62
 
47
63
  def short_call_description
@@ -275,6 +275,7 @@ module Mocha
275
275
  @everything_stubbed = false
276
276
  @responder = nil
277
277
  @unexpected_invocation = nil
278
+ @expired = false
278
279
  end
279
280
 
280
281
  # @private
@@ -305,26 +306,16 @@ module Mocha
305
306
  end
306
307
 
307
308
  # @private
308
- # rubocop:disable Style/MethodMissingSuper,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
309
- def method_missing(symbol, *arguments, &block)
310
- if @responder && !@responder.respond_to?(symbol)
311
- raise NoMethodError, "undefined method `#{symbol}' for #{mocha_inspect} which responds like #{@responder.mocha_inspect}"
312
- end
313
- invocation = Invocation.new(self, symbol, *arguments)
309
+ def method_missing(symbol, *arguments, &block) # rubocop:disable Style/MethodMissingSuper
310
+ check_expiry
311
+ check_responder_responds_to(symbol)
312
+ invocation = Invocation.new(self, symbol, *arguments, &block)
314
313
  if (matching_expectation_allowing_invocation = all_expectations.match_allowing_invocation(invocation))
315
- matching_expectation_allowing_invocation.invoke(invocation, &block)
314
+ matching_expectation_allowing_invocation.invoke(invocation)
316
315
  elsif (matching_expectation = all_expectations.match(invocation)) || (!matching_expectation && !@everything_stubbed)
317
- if @unexpected_invocation.nil?
318
- @unexpected_invocation = invocation
319
- matching_expectation.invoke(invocation, &block) if matching_expectation
320
- message = "#{@unexpected_invocation.call_description}\n#{@mockery.mocha_inspect}"
321
- else
322
- message = @unexpected_invocation.short_call_description
323
- end
324
- raise ExpectationErrorFactory.build("unexpected invocation: #{message}", caller)
316
+ raise_unexpected_invocation_error(invocation, matching_expectation)
325
317
  end
326
318
  end
327
- # rubocop:enable Style/MethodMissingSuper,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
328
319
 
329
320
  # @private
330
321
  def respond_to_missing?(symbol, include_private = false)
@@ -351,6 +342,11 @@ module Mocha
351
342
  @expectations.verified?(assertion_counter)
352
343
  end
353
344
 
345
+ # @private
346
+ def __expire__
347
+ @expired = true
348
+ end
349
+
354
350
  # @private
355
351
  def mocha_inspect
356
352
  @name.mocha_inspect
@@ -370,5 +366,35 @@ module Mocha
370
366
  def any_expectations?
371
367
  @expectations.any?
372
368
  end
369
+
370
+ private
371
+
372
+ def raise_unexpected_invocation_error(invocation, matching_expectation)
373
+ if @unexpected_invocation.nil?
374
+ @unexpected_invocation = invocation
375
+ matching_expectation.invoke(invocation) if matching_expectation
376
+ message = "#{@unexpected_invocation.call_description}\n#{@mockery.mocha_inspect}"
377
+ else
378
+ message = @unexpected_invocation.short_call_description
379
+ end
380
+ raise ExpectationErrorFactory.build("unexpected invocation: #{message}", caller)
381
+ end
382
+
383
+ def check_responder_responds_to(symbol)
384
+ if @responder && !@responder.respond_to?(symbol) # rubocop:disable Style/GuardClause
385
+ raise NoMethodError, "undefined method `#{symbol}' for #{mocha_inspect} which responds like #{@responder.mocha_inspect}"
386
+ end
387
+ end
388
+
389
+ def check_expiry
390
+ if @expired # rubocop:disable Style/GuardClause
391
+ Deprecation.warning(
392
+ "#{mocha_inspect} was instantiated in one test but it is receiving invocations within another test.",
393
+ ' This can lead to unintended interactions between tests and hence unexpected test failures.',
394
+ ' Ensure that every test correctly cleans up any state that it introduces.',
395
+ ' A Mocha::StubbingError will be raised in this scenario in the future.'
396
+ )
397
+ end
398
+ end
373
399
  end
374
400
  end
@@ -102,6 +102,7 @@ module Mocha
102
102
 
103
103
  def teardown
104
104
  stubba.unstub_all
105
+ mocks.each(&:__expire__)
105
106
  reset
106
107
  end
107
108
 
@@ -127,19 +128,20 @@ module Mocha
127
128
 
128
129
  def on_stubbing(object, method)
129
130
  method = PRE_RUBY_V19 ? method.to_s : method.to_sym
130
- method_signature = "#{object.mocha_inspect}.#{method}"
131
- check(:stubbing_non_existent_method, 'non-existent method', method_signature) do
131
+ signature_proc = lambda { "#{object.mocha_inspect}.#{method}" }
132
+ check(:stubbing_non_existent_method, 'non-existent method', signature_proc) do
132
133
  !(object.stubba_class.__method_exists__?(method, true) || object.respond_to?(method.to_sym))
133
134
  end
134
- check(:stubbing_non_public_method, 'non-public method', method_signature) do
135
+ check(:stubbing_non_public_method, 'non-public method', signature_proc) do
135
136
  object.stubba_class.__method_exists__?(method, false)
136
137
  end
137
- check(:stubbing_method_on_nil, 'method on nil', method_signature) { object.nil? }
138
- check(:stubbing_method_on_non_mock_object, 'method on non-mock object', method_signature)
138
+ check(:stubbing_method_on_nil, 'method on nil', signature_proc) { object.nil? }
139
+ check(:stubbing_method_on_non_mock_object, 'method on non-mock object', signature_proc)
139
140
  end
140
141
 
141
142
  def on_stubbing_method_unnecessarily(expectation)
142
- check(:stubbing_method_unnecessarily, 'method unnecessarily', expectation.method_signature, expectation.backtrace)
143
+ signature_proc = lambda { expectation.method_signature }
144
+ check(:stubbing_method_unnecessarily, 'method unnecessarily', signature_proc, expectation.backtrace)
143
145
  end
144
146
 
145
147
  attr_writer :logger
@@ -150,15 +152,13 @@ module Mocha
150
152
 
151
153
  private
152
154
 
153
- def check(action, description, method_signature, backtrace = caller)
154
- return if block_given? && !yield
155
+ def check(action, description, signature_proc, backtrace = caller)
156
+ treatment = Mocha.configuration.send(action)
157
+ return if (treatment == :allow) || (block_given? && !yield)
158
+ method_signature = signature_proc.call
155
159
  message = "stubbing #{description}: #{method_signature}"
156
- case Mocha.configuration.send(action)
157
- when :warn
158
- logger.warn(message)
159
- when :prevent
160
- raise StubbingError.new(message, backtrace)
161
- end
160
+ raise StubbingError.new(message, backtrace) if treatment == :prevent
161
+ logger.warn(message) if treatment == :warn
162
162
  end
163
163
 
164
164
  def expectations
@@ -22,11 +22,10 @@ module Mocha
22
22
  # object.expects(:method_1).with(has_entries('key_1' => 1, 'key_2' => 2))
23
23
  # object.method_1('key_1' => 1, 'key_2' => 99)
24
24
  # # error raised, because method_1 was not called with Hash containing entries: 'key_1' => 1, 'key_2' => 2
25
- # rubocop:disable Naming/PredicateName
26
- def has_entries(entries)
25
+ #
26
+ def has_entries(entries) # rubocop:disable Naming/PredicateName
27
27
  HasEntries.new(entries)
28
28
  end
29
- # rubocop:enable Naming/PredicateName
30
29
 
31
30
  # Parameter matcher which matches when actual parameter contains all expected +Hash+ entries.
32
31
  class HasEntries < Base
@@ -39,8 +39,8 @@ module Mocha
39
39
  # object.expects(:method_1).with(has_entry('key_1' => 1))
40
40
  # object.method_1('key_1' => 2, 'key_2' => 1)
41
41
  # # error raised, because method_1 was not called with Hash containing entry: 'key_1' => 1
42
- # rubocop:disable Naming/PredicateName
43
- def has_entry(*options)
42
+ #
43
+ def has_entry(*options) # rubocop:disable Naming/PredicateName
44
44
  case options.length
45
45
  when 1
46
46
  case options[0]
@@ -63,7 +63,6 @@ module Mocha
63
63
  end
64
64
  HasEntry.new(key, value)
65
65
  end
66
- # rubocop:enable Naming/PredicateName
67
66
 
68
67
  # Parameter matcher which matches when actual parameter contains expected +Hash+ entry.
69
68
  class HasEntry < Base