rspec-mocks 3.10.2 → 3.12.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8df50d671b287d9eea08c7e0af0cc98ae18da52ce63543c0e48378d4230a889f
4
- data.tar.gz: 0e8e4186d4eefc8344439185e0533a53b980fd983f80d8faf600c5fe7f5ebf2d
3
+ metadata.gz: 9ac306bd185750c3017ee678b47a8049e734c0442b6cef60e8e7a04aa13c29c4
4
+ data.tar.gz: bde012659ef5fb279c0dee84a6788ba3a58156bfca1d3bdf934c99e6b96c26dc
5
5
  SHA512:
6
- metadata.gz: 0b687302ef0bd48764d9b78df91c0ce9f4918e9697493fbf0d4083f77ac4bd99879a68975bca874b06a887d1f83bcaaca35f476d4a4036286684c37bb3e040c6
7
- data.tar.gz: 102e13e93f56865812cf40a46e3be075f67984dde3eaae091b3b14ffae2c96623f6c2e85112c6ffe759fc7be83c4ba8d0133b59fa91d5d0a3055307dc5c13273
6
+ metadata.gz: ccde683caf2726c2f7e9f27d982550a779fdaead2c595495107dab5cdab04609568aedb882fcf47456528a4630dd55ed8c4097fc169ff71e34cc28e724306879
7
+ data.tar.gz: dec3ab40874ab16f87a20f0332f15afe7a487dd024bcd111843e1edcbfff91366954012d56e2c90e8b7b0518f721cc4f1e9771afad0e0a265034d63c3c6d9b24
checksums.yaml.gz.sig CHANGED
Binary file
data/Changelog.md CHANGED
@@ -1,5 +1,100 @@
1
1
  ### Development
2
- [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.10.2...main)
2
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.5...3-12-maintenance)
3
+
4
+ ### 3.12.5 / 2023-03-30
5
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.4...v3.12.5)
6
+
7
+ Bug Fixes:
8
+
9
+ * Fix compatibility issue with Rails where active_support monkey patches `with`
10
+ when using any instance. (Lachlan Sylvester, #1540)
11
+
12
+ ### 3.12.4 / 2023-03-12
13
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.3...v3.12.4)
14
+
15
+ Bug Fixes:
16
+
17
+ * Fix an issue with asserting that Array#reverse is never called. (Brad Trick, #1533)
18
+ * Fix compatibility issue with Rails where active_support monkey patches `with`.
19
+ (Jean Boussier, #1531, #1534)
20
+
21
+ ### 3.12.3 / 2023-01-17
22
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.2...v3.12.3)
23
+
24
+ Bug Fixes:
25
+
26
+ * Fix keyword delegation in `send` for verifying doubles on Ruby 3.
27
+ (Charlie Honig, #1485)
28
+
29
+ ### 3.12.2 / 2023-01-07
30
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.1...v3.12.2)
31
+
32
+ Bug Fixes:
33
+
34
+ * Fix implementation blocks for mocks using keyword arguments on Ruby 3.2.0.
35
+ (Adam Steel, #1508)
36
+ * Fix keyword argument assertions when mocking using `with` on Ruby 3.2.0.
37
+ (Slava Kardakov, Benoit Tigeot, Phil Pirozhkov, Benoit Daloze, #1514)
38
+
39
+ ### 3.12.1 / 2022-12-10
40
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.0...v3.12.1)
41
+
42
+ Bug Fixes:
43
+
44
+ * Remove empty diff marker when a diff only contains console codes. (Jon Rowe, #1506)
45
+ * Show keyword vs hash diff marker when arguments are not `==` (Jon Rowe, #1506)
46
+ * Change check to detect frozen objects to rescue errors rather than
47
+ pre-empting by checking `frozen?` due to some objects mis-behaving.
48
+ (Keegan Roth, #1401)
49
+ * Prevent unfulfilled expectations using `expect_any_instance_of` across a class
50
+ inheritance boundary from raising rather than failing. (Jon Rowe, #1496)
51
+ * Prevent a misleading error message when using `allow(...).not_to` with
52
+ unsupported matchers. (Phil Pirozhkov, #1503)
53
+
54
+ ### 3.12.0 / 2022-10-26
55
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.11.2...v3.12.0)
56
+
57
+ Enhancements:
58
+
59
+ * Improve diff output when diffing keyword arguments against hashes.
60
+ (Jean Boussier, #1461)
61
+
62
+ ### 3.11.2 / 2022-10-25
63
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.11.1...v3.11.2)
64
+
65
+ Bug Fixes:
66
+
67
+ * Use the original implementation of `Class.new` to detect overridden definitions
68
+ of `new` rather than the owner, fixing detection of "double aliased" methods
69
+ in Ruby 3 and above. (Benoit Daloze, #1470, #1476)
70
+ * Support keyword argument semantics when constraining argument expectations using
71
+ `with` on Ruby 3.0+ with `instance_double` (Andrii Malyshko, #1473)
72
+
73
+ ### 3.11.1 / 2022-03-31
74
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.11.0...v3.11.1)
75
+
76
+ Bug Fixes:
77
+
78
+ * Add extra `ruby2_keywords` calls to properly designate methods using
79
+ `*args` to pass keyword around, fixes an issue with TruffleRuby.
80
+ (Benoit Daloze, #1464)
81
+
82
+ ### 3.11.0 / 2022-02-09
83
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.10.3...v3.11.0)
84
+
85
+ Enhancements:
86
+
87
+ * Add `and_invoke` implementation for configuring responses to `receive`
88
+ (and `receive_messages`) with multiple callable objects. (Kyle Smith, #1411)
89
+
90
+ ### 3.10.3 / 2022-01-28
91
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.10.2...v3.10.3)
92
+
93
+ Bug Fixes:
94
+
95
+ * Suppress warning by setting `$VERBOSE` to nil. (Nobuyoshi Nakada, #1414)
96
+ * Support keyword argument semantics when constraining argument expectations using
97
+ `with` on Ruby 3.0+ (Yusuke Endoh, #1394)
3
98
 
4
99
  ### 3.10.2 / 2021-01-27
5
100
  [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.10.1...v3.10.2)
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # RSpec Mocks [![Build Status](https://github.com/rspec/rspec-mocks/workflows/RSpec%20CI/badge.svg?branch=3-10-maintenance)](https://github.com/rspec/rspec-mocks/actions) [![Code Climate](https://codeclimate.com/github/rspec/rspec-mocks.svg)](https://codeclimate.com/github/rspec/rspec-mocks)
1
+ # RSpec Mocks [![Build Status](https://github.com/rspec/rspec-mocks/workflows/RSpec%20CI/badge.svg)](https://github.com/rspec/rspec-mocks/actions) [![Code Climate](https://codeclimate.com/github/rspec/rspec-mocks.svg)](https://codeclimate.com/github/rspec/rspec-mocks)
2
2
  rspec-mocks is a test-double framework for rspec with support for method stubs,
3
3
  fakes, and message expectations on generated test-doubles and real objects
4
4
  alike.
@@ -49,7 +49,7 @@ module RSpec
49
49
  # @private
50
50
  def unfulfilled_expectations
51
51
  @chains_by_method_name.map do |method_name, chains|
52
- method_name.to_s if ExpectationChain === chains.last unless chains.last.expectation_fulfilled?
52
+ method_name.to_s if ExpectationChain === chains.last && !chains.last.expectation_fulfilled?
53
53
  end.compact
54
54
  end
55
55
 
@@ -10,7 +10,7 @@ module RSpec
10
10
  #
11
11
  # This proxy sits in front of the recorder and delegates both to it
12
12
  # and to the `RSpec::Mocks::Proxy` for each already mocked or stubbed
13
- # instance of the class, in order to propogates changes to the instances.
13
+ # instance of the class, in order to propagates changes to the instances.
14
14
  #
15
15
  # Note that unlike `RSpec::Mocks::Proxy`, this proxy class is stateless
16
16
  # and is not persisted in `RSpec::Mocks.space`.
@@ -83,6 +83,15 @@ module RSpec
83
83
  end
84
84
  end
85
85
 
86
+ unless defined?(BasicObject)
87
+ class BasicObject
88
+ # Remove all methods except those expected to be defined on BasicObject
89
+ (instance_methods.map(&:to_sym) - [:__send__, :"!", :instance_eval, :==, :instance_exec, :"!=", :equal?, :__id__, :__binding__, :object_id]).each do |method|
90
+ undef_method method
91
+ end
92
+ end
93
+ end
94
+
86
95
  # @private
87
96
  # Delegates messages to each of the given targets in order to
88
97
  # provide the fluent interface that is available off of message
@@ -91,12 +100,12 @@ module RSpec
91
100
  # `targets` will typically contain 1 of the `AnyInstance::Recorder`
92
101
  # return values and N `MessageExpectation` instances (one per instance
93
102
  # of the `any_instance` klass).
94
- class FluentInterfaceProxy
103
+ class FluentInterfaceProxy < BasicObject
95
104
  def initialize(targets)
96
105
  @targets = targets
97
106
  end
98
107
 
99
- if RUBY_VERSION.to_f > 1.8
108
+ if ::RUBY_VERSION.to_f > 1.8
100
109
  def respond_to_missing?(method_name, include_private=false)
101
110
  super || @targets.first.respond_to?(method_name, include_private)
102
111
  end
@@ -46,17 +46,34 @@ module RSpec
46
46
  @expected_args = expected_args
47
47
  ensure_expected_args_valid!
48
48
  end
49
+ ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true)
49
50
 
50
51
  # @api public
51
- # @param [Array] args
52
+ # @param [Array] actual_args
52
53
  #
53
54
  # Matches each element in the `expected_args` against the element in the same
54
55
  # position of the arguments passed to `new`.
55
56
  #
56
57
  # @see #initialize
57
- def args_match?(*args)
58
- Support::FuzzyMatcher.values_match?(resolve_expected_args_based_on(args), args)
58
+ def args_match?(*actual_args)
59
+ expected_args = resolve_expected_args_based_on(actual_args)
60
+
61
+ return false if expected_args.size != actual_args.size
62
+
63
+ if RUBY_VERSION >= "3"
64
+ # If the expectation was set with keywords, while the actual method was called with a positional hash argument, they don't match.
65
+ # If the expectation was set without keywords, e.g., with({a: 1}), then it fine to call it with either foo(a: 1) or foo({a: 1}).
66
+ # This corresponds to Ruby semantics, as if the method was def foo(options).
67
+ if Hash === expected_args.last && Hash === actual_args.last
68
+ if !Hash.ruby2_keywords_hash?(actual_args.last) && Hash.ruby2_keywords_hash?(expected_args.last)
69
+ return false
70
+ end
71
+ end
72
+ end
73
+
74
+ Support::FuzzyMatcher.values_match?(expected_args, actual_args)
59
75
  end
76
+ ruby2_keywords :args_match? if respond_to?(:ruby2_keywords, true)
60
77
 
61
78
  # @private
62
79
  # Resolves abstract arg placeholders like `no_args` and `any_args` into
@@ -268,11 +268,32 @@ module RSpec
268
268
  def error_message(expectation, args_for_multiple_calls)
269
269
  expected_args = format_args(expectation.expected_args)
270
270
  actual_args = format_received_args(args_for_multiple_calls)
271
+
272
+ if RSpec::Support::RubyFeatures.distincts_kw_args_from_positional_hash?
273
+ expected_hash = expectation.expected_args.last
274
+ actual_hash = args_for_multiple_calls.last.last
275
+ if Hash === expected_hash && Hash === actual_hash &&
276
+ (Hash.ruby2_keywords_hash?(expected_hash) != Hash.ruby2_keywords_hash?(actual_hash))
277
+
278
+ actual_description = Hash.ruby2_keywords_hash?(actual_hash) ? " (keyword arguments)" : " (options hash)"
279
+ expected_description = Hash.ruby2_keywords_hash?(expected_hash) ? " (keyword arguments)" : " (options hash)"
280
+
281
+ if actual_description != expected_description
282
+ actual_args += actual_description
283
+ expected_args += expected_description
284
+ end
285
+ end
286
+ end
287
+
271
288
  message = default_error_message(expectation, expected_args, actual_args)
272
289
 
273
290
  if args_for_multiple_calls.one?
274
291
  diff = diff_message(expectation.expected_args, args_for_multiple_calls.first)
275
- message << "\nDiff:#{diff}" unless diff.strip.empty?
292
+ if RSpec::Mocks.configuration.color?
293
+ message << "\nDiff:#{diff}" unless diff.gsub(/\e\[\d+m/, '').strip.empty?
294
+ else
295
+ message << "\nDiff:#{diff}" unless diff.strip.empty?
296
+ end
276
297
  end
277
298
 
278
299
  message
@@ -16,7 +16,7 @@ module RSpec
16
16
  @subject = nil
17
17
  end
18
18
 
19
- def name
19
+ def matcher_name
20
20
  "have_received"
21
21
  end
22
22
 
@@ -13,7 +13,7 @@ module RSpec
13
13
  @recorded_customizations = []
14
14
  end
15
15
 
16
- def name
16
+ def matcher_name
17
17
  "receive"
18
18
  end
19
19
 
@@ -55,13 +55,15 @@ module RSpec
55
55
  setup_any_instance_method_substitute(subject, :stub, block)
56
56
  end
57
57
 
58
+ own_methods = (instance_methods - superclass.instance_methods)
58
59
  MessageExpectation.public_instance_methods(false).each do |method|
59
- next if method_defined?(method)
60
+ next if own_methods.include?(method)
60
61
 
61
62
  define_method(method) do |*args, &block|
62
63
  @recorded_customizations << ExpectationCustomization.new(method, args, block)
63
64
  self
64
65
  end
66
+ ruby2_keywords(method) if respond_to?(:ruby2_keywords, true)
65
67
  end
66
68
 
67
69
  private
@@ -13,14 +13,14 @@ module RSpec
13
13
  @recorded_customizations = []
14
14
  end
15
15
 
16
- [:with, :and_return, :and_throw, :and_raise, :and_yield, :and_call_original].each do |msg|
16
+ [:with, :and_return, :and_invoke, :and_throw, :and_raise, :and_yield, :and_call_original].each do |msg|
17
17
  define_method(msg) do |*args, &block|
18
18
  @recorded_customizations << ExpectationCustomization.new(msg, args, block)
19
19
  self
20
20
  end
21
21
  end
22
22
 
23
- def name
23
+ def matcher_name
24
24
  "receive_message_chain"
25
25
  end
26
26
 
@@ -10,7 +10,7 @@ module RSpec
10
10
  @backtrace_line = CallerFilter.first_non_rspec_line
11
11
  end
12
12
 
13
- def name
13
+ def matcher_name
14
14
  "receive_messages"
15
15
  end
16
16
 
@@ -53,7 +53,7 @@ module RSpec
53
53
  # etc.
54
54
  #
55
55
  # If the message is received more times than there are values, the last
56
- # value is received for every subsequent call.
56
+ # value is returned for every subsequent call.
57
57
  #
58
58
  # @return [nil] No further chaining is supported after this.
59
59
  # @example
@@ -85,6 +85,48 @@ module RSpec
85
85
  nil
86
86
  end
87
87
 
88
+ # Tells the object to invoke a Proc when it receives the message. Given
89
+ # more than one value, the result of the first Proc is returned the first
90
+ # time the message is received, the result of the second Proc is returned
91
+ # the next time, etc, etc.
92
+ #
93
+ # If the message is received more times than there are Procs, the result of
94
+ # the last Proc is returned for every subsequent call.
95
+ #
96
+ # @return [nil] No further chaining is supported after this.
97
+ # @example
98
+ # allow(api).to receive(:get_foo).and_invoke(-> { raise ApiTimeout })
99
+ # api.get_foo # => raises ApiTimeout
100
+ # api.get_foo # => raises ApiTimeout
101
+ #
102
+ # allow(api).to receive(:get_foo).and_invoke(-> { raise ApiTimeout }, -> { raise ApiTimeout }, -> { :a_foo })
103
+ # api.get_foo # => raises ApiTimeout
104
+ # api.get_foo # => rasies ApiTimeout
105
+ # api.get_foo # => :a_foo
106
+ # api.get_foo # => :a_foo
107
+ # api.get_foo # => :a_foo
108
+ # # etc
109
+ def and_invoke(first_proc, *procs)
110
+ raise_already_invoked_error_if_necessary(__method__)
111
+ if negative?
112
+ raise "`and_invoke` is not supported with negative message expectations"
113
+ end
114
+
115
+ if block_given?
116
+ raise ArgumentError, "Implementation blocks aren't supported with `and_invoke`"
117
+ end
118
+
119
+ procs.unshift(first_proc)
120
+ if procs.any? { |p| !p.respond_to?(:call) }
121
+ raise ArgumentError, "Arguments to `and_invoke` must be callable."
122
+ end
123
+
124
+ @expected_received_count = [@expected_received_count, procs.size].max unless ignoring_args? || (@expected_received_count == 0 && @at_least)
125
+ self.terminal_implementation_action = AndInvokeImplementation.new(procs)
126
+
127
+ nil
128
+ end
129
+
88
130
  # Tells the object to delegate to the original unmodified method
89
131
  # when it receives the message.
90
132
  #
@@ -97,9 +139,12 @@ module RSpec
97
139
  # counter.increment
98
140
  # expect(counter.count).to eq(original_count + 1)
99
141
  def and_call_original
100
- wrap_original(__method__) do |original, *args, &block|
101
- original.call(*args, &block)
142
+ block = lambda do |original, *args, &b|
143
+ original.call(*args, &b)
102
144
  end
145
+ block = block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
146
+
147
+ wrap_original(__method__, &block)
103
148
  end
104
149
 
105
150
  # Decorates the stubbed method with the supplied block. The original
@@ -322,6 +367,7 @@ module RSpec
322
367
  @argument_list_matcher = ArgumentListMatcher.new(*args)
323
368
  self
324
369
  end
370
+ ruby2_keywords(:with) if respond_to?(:ruby2_keywords, true)
325
371
 
326
372
  # Expect messages to be received in a specific order.
327
373
  #
@@ -360,7 +406,6 @@ module RSpec
360
406
  # some collaborators it delegates to for this stuff but for now this was
361
407
  # the simplest way to split the public from private stuff to make it
362
408
  # easier to publish the docs for the APIs we want published.
363
- # rubocop:disable Metrics/ModuleLength
364
409
  module ImplementationDetails
365
410
  attr_accessor :error_generator, :implementation
366
411
  attr_reader :message
@@ -418,18 +463,22 @@ module RSpec
418
463
  def matches?(message, *args)
419
464
  @message == message && @argument_list_matcher.args_match?(*args)
420
465
  end
466
+ ruby2_keywords :matches? if respond_to?(:ruby2_keywords, true)
421
467
 
422
468
  def safe_invoke(parent_stub, *args, &block)
423
469
  invoke_incrementing_actual_calls_by(1, false, parent_stub, *args, &block)
424
470
  end
471
+ ruby2_keywords :safe_invoke if respond_to?(:ruby2_keywords, true)
425
472
 
426
473
  def invoke(parent_stub, *args, &block)
427
474
  invoke_incrementing_actual_calls_by(1, true, parent_stub, *args, &block)
428
475
  end
476
+ ruby2_keywords :invoke if respond_to?(:ruby2_keywords, true)
429
477
 
430
478
  def invoke_without_incrementing_received_count(parent_stub, *args, &block)
431
479
  invoke_incrementing_actual_calls_by(0, true, parent_stub, *args, &block)
432
480
  end
481
+ ruby2_keywords :invoke_without_incrementing_received_count if respond_to?(:ruby2_keywords, true)
433
482
 
434
483
  def negative?
435
484
  @expected_received_count == 0 && !@at_least
@@ -578,6 +627,7 @@ module RSpec
578
627
  @actual_received_count += increment
579
628
  end
580
629
  end
630
+ ruby2_keywords :invoke_incrementing_actual_calls_by if respond_to?(:ruby2_keywords, true)
581
631
 
582
632
  def has_been_invoked?
583
633
  @actual_received_count > 0
@@ -635,7 +685,6 @@ module RSpec
635
685
  nil
636
686
  end
637
687
  end
638
- # rubocop:enable Metrics/ModuleLength
639
688
 
640
689
  include ImplementationDetails
641
690
  end
@@ -683,6 +732,24 @@ module RSpec
683
732
  end
684
733
  end
685
734
 
735
+ # Handles the implementation of an `and_invoke` implementation.
736
+ # @private
737
+ class AndInvokeImplementation
738
+ def initialize(procs_to_invoke)
739
+ @procs_to_invoke = procs_to_invoke
740
+ end
741
+
742
+ def call(*args, &block)
743
+ proc = if @procs_to_invoke.size > 1
744
+ @procs_to_invoke.shift
745
+ else
746
+ @procs_to_invoke.first
747
+ end
748
+
749
+ proc.call(*args, &block)
750
+ end
751
+ end
752
+
686
753
  # Represents a configured implementation. Takes into account
687
754
  # any number of sub-implementations.
688
755
  # @private
@@ -694,6 +761,7 @@ module RSpec
694
761
  action.call(*args, &block)
695
762
  end.last
696
763
  end
764
+ ruby2_keywords :call if respond_to?(:ruby2_keywords, true)
697
765
 
698
766
  def present?
699
767
  actions.any?
@@ -739,6 +807,7 @@ module RSpec
739
807
  def call(*args, &block)
740
808
  @block.call(@method, *args, &block)
741
809
  end
810
+ ruby2_keywords :call if respond_to?(:ruby2_keywords, true)
742
811
 
743
812
  private
744
813
 
@@ -2,6 +2,9 @@ module RSpec
2
2
  module Mocks
3
3
  # @private
4
4
  class MethodDouble
5
+ # @private TODO: drop in favor of FrozenError in ruby 2.5+
6
+ FROZEN_ERROR_MSG = /can't modify frozen/
7
+
5
8
  # @private
6
9
  attr_reader :method_name, :object, :expectations, :stubs, :method_stasher
7
10
 
@@ -63,11 +66,21 @@ module RSpec
63
66
  define_method(method_name) do |*args, &block|
64
67
  method_double.proxy_method_invoked(self, *args, &block)
65
68
  end
69
+ # This can't be `if respond_to?(:ruby2_keywords, true)`,
70
+ # see https://github.com/rspec/rspec-mocks/pull/1385#issuecomment-755340298
66
71
  ruby2_keywords(method_name) if Module.private_method_defined?(:ruby2_keywords)
67
72
  __send__(visibility, method_name)
68
73
  end
69
74
 
70
75
  @method_is_proxied = true
76
+ rescue RuntimeError, TypeError => e
77
+ # TODO: drop in favor of FrozenError in ruby 2.5+
78
+ # RuntimeError (and FrozenError) for ruby 2.x
79
+ # TypeError for ruby 1.x
80
+ if (defined?(FrozenError) && e.is_a?(FrozenError)) || FROZEN_ERROR_MSG === e.message
81
+ raise ArgumentError, "Cannot proxy frozen objects, rspec-mocks relies on proxies for method stubbing and expectations."
82
+ end
83
+ raise
71
84
  end
72
85
 
73
86
  # The implementation of the proxied method. Subclasses may override this
@@ -77,10 +90,10 @@ module RSpec
77
90
  def proxy_method_invoked(_obj, *args, &block)
78
91
  @proxy.message_received method_name, *args, &block
79
92
  end
93
+ ruby2_keywords :proxy_method_invoked if respond_to?(:ruby2_keywords, true)
80
94
 
81
95
  # @private
82
96
  def restore_original_method
83
- return show_frozen_warning if object_singleton_class.frozen?
84
97
  return unless @method_is_proxied
85
98
 
86
99
  remove_method_from_definition_target
@@ -88,6 +101,14 @@ module RSpec
88
101
  restore_original_visibility
89
102
 
90
103
  @method_is_proxied = false
104
+ rescue RuntimeError, TypeError => e
105
+ # TODO: drop in favor of FrozenError in ruby 2.5+
106
+ # RuntimeError (and FrozenError) for ruby 2.x
107
+ # TypeError for ruby 1.x
108
+ if (defined?(FrozenError) && e.is_a?(FrozenError)) || FROZEN_ERROR_MSG === e.message
109
+ return show_frozen_warning
110
+ end
111
+ raise
91
112
  end
92
113
 
93
114
  # @private
@@ -185,11 +185,23 @@ module RSpec
185
185
  def self.applies_to?(method_name)
186
186
  return false unless method_name == :new
187
187
  klass = yield
188
- return false unless klass.respond_to?(:new, true)
188
+ return false unless ::Class === klass && klass.respond_to?(:new, true)
189
189
 
190
190
  # We only want to apply our special logic to normal `new` methods.
191
191
  # Methods that the user has monkeyed with should be left as-is.
192
- ::RSpec::Support.method_handle_for(klass, :new).owner == ::Class
192
+ uses_class_new?(klass)
193
+ end
194
+
195
+ if RUBY_VERSION.to_i >= 3
196
+ CLASS_NEW = ::Class.instance_method(:new)
197
+
198
+ def self.uses_class_new?(klass)
199
+ ::RSpec::Support.method_handle_for(klass, :new) == CLASS_NEW.bind(klass)
200
+ end
201
+ else # Ruby 2's Method#== is too strict
202
+ def self.uses_class_new?(klass)
203
+ ::RSpec::Support.method_handle_for(klass, :new).owner == ::Class
204
+ end
193
205
  end
194
206
 
195
207
  def with_signature
@@ -37,7 +37,7 @@ if defined?(::Minitest::Expectation)
37
37
  # not want to here (or else we would interfere with rspec-expectations' definition).
38
38
  else
39
39
  # ...otherwise, define those methods now. If `rspec/expectations/minitest_integration`
40
- # is loaded after this file, it'll overide the defintion here.
40
+ # is loaded after this file, it'll override the definition here.
41
41
  Minitest::Expectation.class_eval do
42
42
  include RSpec::Mocks::ExpectationTargetMethods
43
43
 
@@ -81,7 +81,7 @@ module RSpec
81
81
  # Queries rspec-mocks to find out information about the named constant.
82
82
  #
83
83
  # @param [String] name the name of the constant
84
- # @return [Constant] an object contaning information about the named
84
+ # @return [Constant] an object containing information about the named
85
85
  # constant.
86
86
  def self.original(name)
87
87
  mutator = ::RSpec::Mocks.space.constant_mutator_for(name)
@@ -35,15 +35,9 @@ module RSpec
35
35
 
36
36
  # @private
37
37
  def ensure_can_be_proxied!(object)
38
- return unless object.is_a?(Symbol) || object.frozen?
39
- return if object.nil?
38
+ return unless object.is_a?(Symbol)
40
39
 
41
- msg = "Cannot proxy frozen objects"
42
- if Symbol === object
43
- msg << ". Symbols such as #{object} cannot be mocked or stubbed."
44
- else
45
- msg << ", rspec-mocks relies on proxies for method stubbing and expectations."
46
- end
40
+ msg = "Cannot proxy frozen objects. Symbols such as #{object} cannot be mocked or stubbed."
47
41
  raise ArgumentError, msg
48
42
  end
49
43
 
@@ -198,6 +192,7 @@ module RSpec
198
192
  @messages_received << [message, args, block]
199
193
  end
200
194
  end
195
+ ruby2_keywords :record_message_received if respond_to?(:ruby2_keywords, true)
201
196
 
202
197
  # @private
203
198
  def message_received(message, *args, &block)
@@ -230,6 +225,7 @@ module RSpec
230
225
  @object.__send__(:method_missing, message, *args, &block)
231
226
  end
232
227
  end
228
+ ruby2_keywords :message_received if respond_to?(:ruby2_keywords, true)
233
229
 
234
230
  # @private
235
231
  def raise_unexpected_message_error(method_name, args)
@@ -279,12 +275,14 @@ module RSpec
279
275
  expectation.matches?(method_name, *args)
280
276
  end
281
277
  end
278
+ ruby2_keywords :find_matching_expectation if respond_to?(:ruby2_keywords, true)
282
279
 
283
280
  def find_almost_matching_expectation(method_name, *args)
284
281
  find_best_matching_expectation_for(method_name) do |expectation|
285
282
  expectation.matches_name_but_not_args(method_name, *args)
286
283
  end
287
284
  end
285
+ ruby2_keywords :find_almost_matching_expectation if respond_to?(:ruby2_keywords, true)
288
286
 
289
287
  def find_best_matching_expectation_for(method_name)
290
288
  first_match = nil
@@ -301,10 +299,12 @@ module RSpec
301
299
  def find_matching_method_stub(method_name, *args)
302
300
  method_double_for(method_name).stubs.find { |stub| stub.matches?(method_name, *args) }
303
301
  end
302
+ ruby2_keywords :find_matching_method_stub if respond_to?(:ruby2_keywords, true)
304
303
 
305
304
  def find_almost_matching_stub(method_name, *args)
306
305
  method_double_for(method_name).stubs.find { |stub| stub.matches_name_but_not_args(method_name, *args) }
307
306
  end
307
+ ruby2_keywords :find_almost_matching_stub if respond_to?(:ruby2_keywords, true)
308
308
  end
309
309
 
310
310
  # @private
@@ -360,6 +360,7 @@ module RSpec
360
360
  end
361
361
  super
362
362
  end
363
+ ruby2_keywords :message_received if respond_to?(:ruby2_keywords, true)
363
364
 
364
365
  private
365
366
 
@@ -77,9 +77,9 @@ module RSpec
77
77
 
78
78
  def reset_all
79
79
  proxies.each_value { |proxy| proxy.reset }
80
- @constant_mutators.reverse.each { |mut| mut.idempotently_reset }
81
80
  any_instance_recorders.each_value { |recorder| recorder.stop_all_observation! }
82
81
  any_instance_recorders.clear
82
+ @constant_mutators.reverse.each { |mut| mut.idempotently_reset }
83
83
  end
84
84
 
85
85
  def register_constant_mutator(mutator)
@@ -54,7 +54,7 @@ module RSpec
54
54
 
55
55
  def raise_negation_unsupported(method_name, matcher)
56
56
  raise NegationUnsupportedError,
57
- "`#{expression}(...).#{method_name} #{matcher.name}` is not supported since it " \
57
+ "`#{expression}(...).#{method_name} #{matcher.matcher_name}` is not supported since it " \
58
58
  "doesn't really make sense. What would it even mean?"
59
59
  end
60
60
  end
@@ -34,27 +34,21 @@ module RSpec
34
34
  super
35
35
  end
36
36
 
37
- # @private
38
- module SilentIO
39
- def self.method_missing(*); end
40
- def self.respond_to?(*)
41
- true
42
- end
43
- end
44
-
45
37
  # Redefining `__send__` causes ruby to issue a warning.
46
- old, $stderr = $stderr, SilentIO
38
+ old, $VERBOSE = $VERBOSE, nil
47
39
  def __send__(name, *args, &block)
48
40
  @__sending_message = name
49
41
  super
50
42
  ensure
51
43
  @__sending_message = nil
52
44
  end
53
- $stderr = old
45
+ ruby2_keywords :__send__ if respond_to?(:ruby2_keywords, true)
46
+ $VERBOSE = old
54
47
 
55
48
  def send(name, *args, &block)
56
49
  __send__(name, *args, &block)
57
50
  end
51
+ ruby2_keywords :send if respond_to?(:ruby2_keywords, true)
58
52
 
59
53
  def initialize(doubled_module, *args)
60
54
  @doubled_module = doubled_module
@@ -31,6 +31,7 @@ module RSpec
31
31
  end
32
32
  end
33
33
  end
34
+ ruby2_keywords(:with) if respond_to?(:ruby2_keywords, true)
34
35
 
35
36
  private
36
37
 
@@ -57,7 +57,7 @@ module RSpec
57
57
  # A verifying proxy mostly acts like a normal proxy, except that it
58
58
  # contains extra logic to try and determine the validity of any expectation
59
59
  # set on it. This includes whether or not methods have been defined and the
60
- # validatiy of arguments on method calls.
60
+ # validity of arguments on method calls.
61
61
  #
62
62
  # In all other ways this behaves like a normal proxy. It only adds the
63
63
  # verification behaviour to specific methods then delegates to the parent
@@ -147,12 +147,12 @@ module RSpec
147
147
  end
148
148
 
149
149
  def add_expectation(*args, &block)
150
- # explict params necessary for 1.8.7 see #626
150
+ # explicit params necessary for 1.8.7 see #626
151
151
  super(*args, &block).tap { |x| x.method_reference = @method_reference }
152
152
  end
153
153
 
154
154
  def add_stub(*args, &block)
155
- # explict params necessary for 1.8.7 see #626
155
+ # explicit params necessary for 1.8.7 see #626
156
156
  super(*args, &block).tap { |x| x.method_reference = @method_reference }
157
157
  end
158
158
 
@@ -160,6 +160,7 @@ module RSpec
160
160
  validate_arguments!(args)
161
161
  super
162
162
  end
163
+ ruby2_keywords :proxy_method_invoked if respond_to?(:ruby2_keywords, true)
163
164
 
164
165
  def validate_arguments!(actual_args)
165
166
  @method_reference.with_signature do |signature|
@@ -3,7 +3,7 @@ module RSpec
3
3
  # Version information for RSpec mocks.
4
4
  module Version
5
5
  # Version of RSpec mocks currently in use in SemVer format.
6
- STRING = '3.10.2'
6
+ STRING = '3.12.5'
7
7
  end
8
8
  end
9
9
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-mocks
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.10.2
4
+ version: 3.12.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Baker
@@ -45,7 +45,7 @@ cert_chain:
45
45
  ZsVDj6a7lH3cNqtWXZxrb2wO38qV5AkYj8SQK7Hj3/Yui9myUX3crr+PdetazSqQ
46
46
  F3MdtaDehhjC
47
47
  -----END CERTIFICATE-----
48
- date: 2021-01-28 00:00:00.000000000 Z
48
+ date: 2023-03-30 00:00:00.000000000 Z
49
49
  dependencies:
50
50
  - !ruby/object:Gem::Dependency
51
51
  name: rspec-support
@@ -53,14 +53,14 @@ dependencies:
53
53
  requirements:
54
54
  - - "~>"
55
55
  - !ruby/object:Gem::Version
56
- version: 3.10.0
56
+ version: 3.12.0
57
57
  type: :runtime
58
58
  prerelease: false
59
59
  version_requirements: !ruby/object:Gem::Requirement
60
60
  requirements:
61
61
  - - "~>"
62
62
  - !ruby/object:Gem::Version
63
- version: 3.10.0
63
+ version: 3.12.0
64
64
  - !ruby/object:Gem::Dependency
65
65
  name: diff-lcs
66
66
  requirement: !ruby/object:Gem::Requirement
@@ -99,30 +99,30 @@ dependencies:
99
99
  name: cucumber
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - "~>"
102
+ - - ">="
103
103
  - !ruby/object:Gem::Version
104
- version: 1.3.15
104
+ version: '1.3'
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - "~>"
109
+ - - ">="
110
110
  - !ruby/object:Gem::Version
111
- version: 1.3.15
111
+ version: '1.3'
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: aruba
114
114
  requirement: !ruby/object:Gem::Requirement
115
115
  requirements:
116
116
  - - "~>"
117
117
  - !ruby/object:Gem::Version
118
- version: 0.14.10
118
+ version: '1.1'
119
119
  type: :development
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
123
  - - "~>"
124
124
  - !ruby/object:Gem::Version
125
- version: 0.14.10
125
+ version: '1.1'
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: minitest
128
128
  requirement: !ruby/object:Gem::Requirement
@@ -194,7 +194,7 @@ licenses:
194
194
  - MIT
195
195
  metadata:
196
196
  bug_tracker_uri: https://github.com/rspec/rspec-mocks/issues
197
- changelog_uri: https://github.com/rspec/rspec-mocks/blob/v3.10.2/Changelog.md
197
+ changelog_uri: https://github.com/rspec/rspec-mocks/blob/v3.12.5/Changelog.md
198
198
  documentation_uri: https://rspec.info/documentation/
199
199
  mailing_list_uri: https://groups.google.com/forum/#!forum/rspec
200
200
  source_code_uri: https://github.com/rspec/rspec-mocks
@@ -214,8 +214,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
214
214
  - !ruby/object:Gem::Version
215
215
  version: '0'
216
216
  requirements: []
217
- rubygems_version: 3.2.4
217
+ rubygems_version: 3.4.1
218
218
  signing_key:
219
219
  specification_version: 4
220
- summary: rspec-mocks-3.10.2
220
+ summary: rspec-mocks-3.12.5
221
221
  test_files: []
metadata.gz.sig CHANGED
Binary file