rspec-mocks 3.11.1 → 3.13.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/Changelog.md +107 -1
- data/README.md +2 -0
- data/lib/rspec/mocks/any_instance/message_chains.rb +1 -1
- data/lib/rspec/mocks/any_instance/proxy.rb +12 -3
- data/lib/rspec/mocks/any_instance/recorder.rb +11 -9
- data/lib/rspec/mocks/argument_list_matcher.rb +3 -1
- data/lib/rspec/mocks/argument_matchers.rb +51 -7
- data/lib/rspec/mocks/configuration.rb +1 -1
- data/lib/rspec/mocks/error_generator.rb +22 -1
- data/lib/rspec/mocks/matchers/have_received.rb +1 -1
- data/lib/rspec/mocks/matchers/receive.rb +3 -2
- data/lib/rspec/mocks/matchers/receive_message_chain.rb +1 -1
- data/lib/rspec/mocks/matchers/receive_messages.rb +1 -1
- data/lib/rspec/mocks/message_expectation.rb +4 -5
- data/lib/rspec/mocks/method_double.rb +30 -5
- data/lib/rspec/mocks/method_reference.rb +14 -2
- data/lib/rspec/mocks/minitest_integration.rb +1 -1
- data/lib/rspec/mocks/mutate_const.rb +1 -1
- data/lib/rspec/mocks/proxy.rb +6 -14
- data/lib/rspec/mocks/space.rb +1 -1
- data/lib/rspec/mocks/syntax.rb +1 -1
- data/lib/rspec/mocks/targets.rb +1 -1
- data/lib/rspec/mocks/verifying_double.rb +2 -0
- data/lib/rspec/mocks/verifying_message_expectation.rb +1 -0
- data/lib/rspec/mocks/verifying_proxy.rb +4 -3
- data/lib/rspec/mocks/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +17 -14
- metadata.gz.sig +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 560dd3294f2da199bebf87e99715e41d9a5859b2a47408121fe449b8614008e1
|
4
|
+
data.tar.gz: 0baffd51e9e653573998948c8057918b0e133caa13435026ad30a30848e15094
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ec16d16de43a63521e1e89111df5b26b009e1dfa6738e802fb79c485a3894a4bdf60b63f08a5420c7a37934f367c93250f112d630f727a552c9ac86ece41b7a
|
7
|
+
data.tar.gz: 7a8e8e5b56dd7e362b7109bce4137c4f77a95eb50d1904fef38c2ff5cb28d605398b653ba9801ca8eab28b6c894d8f787275132d34193f031d7d10c305791e95
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/Changelog.md
CHANGED
@@ -1,5 +1,111 @@
|
|
1
1
|
### Development
|
2
|
-
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.
|
2
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.13.2...3-13-maintennace)
|
3
|
+
|
4
|
+
### 3.13.2 / 2024-10-02
|
5
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.13.1...v3.13.2)
|
6
|
+
|
7
|
+
Bug Fixes:
|
8
|
+
|
9
|
+
* Support keyword arguments in callables passed to `and_invoke`. (Jon Rowe, #1595)
|
10
|
+
|
11
|
+
### 3.13.1 / 2024-05-08
|
12
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.13.0...v3.13.1)
|
13
|
+
|
14
|
+
Bug Fixes:
|
15
|
+
|
16
|
+
* Use `RSpec::Support::Mutex` in `RSpec::Mocks::Proxy` to avoid issues from
|
17
|
+
stubbing `::Mutex#new`. (Eric Mueller, #1575)
|
18
|
+
|
19
|
+
### 3.13.0 / 2024-02-04
|
20
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.7...v3.13.0)
|
21
|
+
|
22
|
+
Enhancements:
|
23
|
+
|
24
|
+
* Add an `array_excluding` matcher for arguments. (Zane Wolfgang Pickett, #1528)
|
25
|
+
|
26
|
+
### 3.12.7 / 2024-02-04
|
27
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.6...v3.12.7)
|
28
|
+
|
29
|
+
Bug Fixes:
|
30
|
+
|
31
|
+
* Reduce allocations from "any_instance" style mocks. (Carlos Palhares, #1479)
|
32
|
+
|
33
|
+
### 3.12.6 / 2023-07-11
|
34
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.5...v3.12.6)
|
35
|
+
|
36
|
+
Bug Fixes:
|
37
|
+
|
38
|
+
* Fix an issue with `and_call_original` when using the `method_missing` fallback
|
39
|
+
with keyword arguments. (Igor Drozdov, #1552)
|
40
|
+
|
41
|
+
### 3.12.5 / 2023-03-30
|
42
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.4...v3.12.5)
|
43
|
+
|
44
|
+
Bug Fixes:
|
45
|
+
|
46
|
+
* Fix compatibility issue with Rails where active_support monkey patches `with`
|
47
|
+
when using any instance. (Lachlan Sylvester, #1540)
|
48
|
+
|
49
|
+
### 3.12.4 / 2023-03-12
|
50
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.3...v3.12.4)
|
51
|
+
|
52
|
+
Bug Fixes:
|
53
|
+
|
54
|
+
* Fix an issue with asserting that Array#reverse is never called. (Brad Trick, #1533)
|
55
|
+
* Fix compatibility issue with Rails where active_support monkey patches `with`.
|
56
|
+
(Jean Boussier, #1531, #1534)
|
57
|
+
|
58
|
+
### 3.12.3 / 2023-01-17
|
59
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.2...v3.12.3)
|
60
|
+
|
61
|
+
Bug Fixes:
|
62
|
+
|
63
|
+
* Fix keyword delegation in `send` for verifying doubles on Ruby 3.
|
64
|
+
(Charlie Honig, #1485)
|
65
|
+
|
66
|
+
### 3.12.2 / 2023-01-07
|
67
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.1...v3.12.2)
|
68
|
+
|
69
|
+
Bug Fixes:
|
70
|
+
|
71
|
+
* Fix implementation blocks for mocks using keyword arguments on Ruby 3.2.0.
|
72
|
+
(Adam Steel, #1508)
|
73
|
+
* Fix keyword argument assertions when mocking using `with` on Ruby 3.2.0.
|
74
|
+
(Slava Kardakov, Benoit Tigeot, Phil Pirozhkov, Benoit Daloze, #1514)
|
75
|
+
|
76
|
+
### 3.12.1 / 2022-12-10
|
77
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.12.0...v3.12.1)
|
78
|
+
|
79
|
+
Bug Fixes:
|
80
|
+
|
81
|
+
* Remove empty diff marker when a diff only contains console codes. (Jon Rowe, #1506)
|
82
|
+
* Show keyword vs hash diff marker when arguments are not `==` (Jon Rowe, #1506)
|
83
|
+
* Change check to detect frozen objects to rescue errors rather than
|
84
|
+
pre-empting by checking `frozen?` due to some objects mis-behaving.
|
85
|
+
(Keegan Roth, #1401)
|
86
|
+
* Prevent unfulfilled expectations using `expect_any_instance_of` across a class
|
87
|
+
inheritance boundary from raising rather than failing. (Jon Rowe, #1496)
|
88
|
+
* Prevent a misleading error message when using `allow(...).not_to` with
|
89
|
+
unsupported matchers. (Phil Pirozhkov, #1503)
|
90
|
+
|
91
|
+
### 3.12.0 / 2022-10-26
|
92
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.11.2...v3.12.0)
|
93
|
+
|
94
|
+
Enhancements:
|
95
|
+
|
96
|
+
* Improve diff output when diffing keyword arguments against hashes.
|
97
|
+
(Jean Boussier, #1461)
|
98
|
+
|
99
|
+
### 3.11.2 / 2022-10-25
|
100
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.11.1...v3.11.2)
|
101
|
+
|
102
|
+
Bug Fixes:
|
103
|
+
|
104
|
+
* Use the original implementation of `Class.new` to detect overridden definitions
|
105
|
+
of `new` rather than the owner, fixing detection of "double aliased" methods
|
106
|
+
in Ruby 3 and above. (Benoit Daloze, #1470, #1476)
|
107
|
+
* Support keyword argument semantics when constraining argument expectations using
|
108
|
+
`with` on Ruby 3.0+ with `instance_double` (Andrii Malyshko, #1473)
|
3
109
|
|
4
110
|
### 3.11.1 / 2022-03-31
|
5
111
|
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.11.0...v3.11.1)
|
data/README.md
CHANGED
@@ -278,6 +278,8 @@ expect(double).to receive(:msg).with(1, duck_type(:abs, :div), "b") #2nd argumen
|
|
278
278
|
expect(double).to receive(:msg).with(hash_including(:a => 5)) # first arg is a hash with a: 5 as one of the key-values
|
279
279
|
expect(double).to receive(:msg).with(array_including(5)) # first arg is an array with 5 as one of the key-values
|
280
280
|
expect(double).to receive(:msg).with(hash_excluding(:a => 5)) # first arg is a hash without a: 5 as one of the key-values
|
281
|
+
expect(double).to receive(:msg).with(start_with('a')) # any matcher, custom or from rspec-expectations
|
282
|
+
expect(double).to receive(:msg).with(satisfy { |data| data.dig(:a, :b, :c) == 5 }) # assert anything you want
|
281
283
|
```
|
282
284
|
|
283
285
|
## Receive Counts
|
@@ -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
|
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
|
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
|
@@ -156,21 +156,23 @@ module RSpec
|
|
156
156
|
|
157
157
|
private
|
158
158
|
|
159
|
-
def ancestor_is_an_observer?(method_name)
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
end
|
165
|
-
end
|
159
|
+
def ancestor_is_an_observer?(ancestor, method_name)
|
160
|
+
return if ancestor == @klass
|
161
|
+
|
162
|
+
::RSpec::Mocks.space.
|
163
|
+
any_instance_recorder_for(ancestor).already_observing?(method_name)
|
166
164
|
end
|
167
165
|
|
168
166
|
def super_class_observers_for(method_name)
|
169
|
-
@klass.ancestors.select
|
167
|
+
@klass.ancestors.select do |ancestor|
|
168
|
+
ancestor_is_an_observer?(ancestor, method_name)
|
169
|
+
end
|
170
170
|
end
|
171
171
|
|
172
172
|
def super_class_observing?(method_name)
|
173
|
-
@klass.ancestors.any?
|
173
|
+
@klass.ancestors.any? do |ancestor|
|
174
|
+
ancestor_is_an_observer?(ancestor, method_name)
|
175
|
+
end
|
174
176
|
end
|
175
177
|
|
176
178
|
def normalize_chain(*args)
|
@@ -61,7 +61,9 @@ module RSpec
|
|
61
61
|
return false if expected_args.size != actual_args.size
|
62
62
|
|
63
63
|
if RUBY_VERSION >= "3"
|
64
|
-
#
|
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).
|
65
67
|
if Hash === expected_args.last && Hash === actual_args.last
|
66
68
|
if !Hash.ruby2_keywords_hash?(actual_args.last) && Hash.ruby2_keywords_hash?(expected_args.last)
|
67
69
|
return false
|
@@ -71,6 +71,16 @@ module RSpec
|
|
71
71
|
HashIncludingMatcher.new(ArgumentMatchers.anythingize_lonely_keys(*args))
|
72
72
|
end
|
73
73
|
|
74
|
+
# Matches a hash that doesn't include the specified key(s) or key/value.
|
75
|
+
#
|
76
|
+
# @example
|
77
|
+
# expect(object).to receive(:message).with(hash_excluding(:key => val))
|
78
|
+
# expect(object).to receive(:message).with(hash_excluding(:key))
|
79
|
+
# expect(object).to receive(:message).with(hash_excluding(:key, :key2 => :val2))
|
80
|
+
def hash_excluding(*args)
|
81
|
+
HashExcludingMatcher.new(ArgumentMatchers.anythingize_lonely_keys(*args))
|
82
|
+
end
|
83
|
+
|
74
84
|
# Matches an array that includes the specified items at least once.
|
75
85
|
# Ignores duplicates and additional values
|
76
86
|
#
|
@@ -82,14 +92,14 @@ module RSpec
|
|
82
92
|
ArrayIncludingMatcher.new(actually_an_array)
|
83
93
|
end
|
84
94
|
|
85
|
-
# Matches
|
95
|
+
# Matches an array that excludes the specified items.
|
86
96
|
#
|
87
97
|
# @example
|
88
|
-
# expect(object).to receive(:message).with(
|
89
|
-
# expect(object).to receive(:message).with(
|
90
|
-
|
91
|
-
|
92
|
-
|
98
|
+
# expect(object).to receive(:message).with(array_excluding(1,2,3))
|
99
|
+
# expect(object).to receive(:message).with(array_excluding([1,2,3]))
|
100
|
+
def array_excluding(*args)
|
101
|
+
actually_an_array = Array === args.first && args.count == 1 ? args.first : args
|
102
|
+
ArrayExcludingMatcher.new(actually_an_array)
|
93
103
|
end
|
94
104
|
|
95
105
|
alias_method :hash_not_including, :hash_excluding
|
@@ -236,6 +246,8 @@ module RSpec
|
|
236
246
|
|
237
247
|
def ===(actual)
|
238
248
|
actual = actual.uniq
|
249
|
+
return true if (actual & @expected).count >= @expected.count
|
250
|
+
|
239
251
|
@expected.uniq.all? do |expected_element|
|
240
252
|
actual.any? do |actual_element|
|
241
253
|
RSpec::Support::FuzzyMatcher.values_match?(expected_element, actual_element)
|
@@ -258,6 +270,38 @@ module RSpec
|
|
258
270
|
end
|
259
271
|
end
|
260
272
|
|
273
|
+
# @private
|
274
|
+
class ArrayExcludingMatcher
|
275
|
+
def initialize(unexpected)
|
276
|
+
@unexpected = unexpected.uniq
|
277
|
+
end
|
278
|
+
|
279
|
+
def ===(actual)
|
280
|
+
actual = actual.uniq
|
281
|
+
return false unless (actual & @unexpected).empty?
|
282
|
+
|
283
|
+
actual.none? do |actual_element|
|
284
|
+
@unexpected.any? do |unexpected_element|
|
285
|
+
RSpec::Support::FuzzyMatcher.values_match?(unexpected_element, actual_element)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
rescue NoMethodError
|
289
|
+
false
|
290
|
+
end
|
291
|
+
|
292
|
+
def description
|
293
|
+
"array_excluding(#{formatted_unexpected_values})"
|
294
|
+
end
|
295
|
+
|
296
|
+
private
|
297
|
+
|
298
|
+
def formatted_unexpected_values
|
299
|
+
@unexpected.map do |x|
|
300
|
+
RSpec::Support.rspec_description_for_object(x)
|
301
|
+
end.join(", ")
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
261
305
|
# @private
|
262
306
|
class DuckTypeMatcher
|
263
307
|
def initialize(*methods_to_respond_to)
|
@@ -312,7 +356,7 @@ module RSpec
|
|
312
356
|
begin
|
313
357
|
object.class.name.include?(matcher_namespace)
|
314
358
|
rescue NoMethodError
|
315
|
-
# Some objects, like BasicObject, don't
|
359
|
+
# Some objects, like BasicObject, don't implement standard
|
316
360
|
# reflection methods.
|
317
361
|
false
|
318
362
|
end
|
@@ -156,7 +156,7 @@ module RSpec
|
|
156
156
|
end
|
157
157
|
|
158
158
|
# @private
|
159
|
-
# Used to track
|
159
|
+
# Used to track whether we are temporarily suppressing verifying partial
|
160
160
|
# doubles with `without_partial_double_verification { ... }`
|
161
161
|
attr_accessor :temporarily_suppress_partial_double_verification
|
162
162
|
|
@@ -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
|
-
|
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
|
@@ -13,7 +13,7 @@ module RSpec
|
|
13
13
|
@recorded_customizations = []
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
16
|
+
def matcher_name
|
17
17
|
"receive"
|
18
18
|
end
|
19
19
|
|
@@ -55,8 +55,9 @@ 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
|
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)
|
@@ -68,7 +68,7 @@ module RSpec
|
|
68
68
|
# counter.count # => 3
|
69
69
|
# counter.count # => 3
|
70
70
|
# # etc
|
71
|
-
def and_return(first_value, *values)
|
71
|
+
def and_return(first_value, *values, &_block)
|
72
72
|
raise_already_invoked_error_if_necessary(__method__)
|
73
73
|
if negative?
|
74
74
|
raise "`and_return` is not supported with negative message expectations"
|
@@ -101,12 +101,12 @@ module RSpec
|
|
101
101
|
#
|
102
102
|
# allow(api).to receive(:get_foo).and_invoke(-> { raise ApiTimeout }, -> { raise ApiTimeout }, -> { :a_foo })
|
103
103
|
# api.get_foo # => raises ApiTimeout
|
104
|
-
# api.get_foo # =>
|
104
|
+
# api.get_foo # => raises ApiTimeout
|
105
105
|
# api.get_foo # => :a_foo
|
106
106
|
# api.get_foo # => :a_foo
|
107
107
|
# api.get_foo # => :a_foo
|
108
108
|
# # etc
|
109
|
-
def and_invoke(first_proc, *procs)
|
109
|
+
def and_invoke(first_proc, *procs, &_block)
|
110
110
|
raise_already_invoked_error_if_necessary(__method__)
|
111
111
|
if negative?
|
112
112
|
raise "`and_invoke` is not supported with negative message expectations"
|
@@ -406,7 +406,6 @@ module RSpec
|
|
406
406
|
# some collaborators it delegates to for this stuff but for now this was
|
407
407
|
# the simplest way to split the public from private stuff to make it
|
408
408
|
# easier to publish the docs for the APIs we want published.
|
409
|
-
# rubocop:disable Metrics/ModuleLength
|
410
409
|
module ImplementationDetails
|
411
410
|
attr_accessor :error_generator, :implementation
|
412
411
|
attr_reader :message
|
@@ -686,7 +685,6 @@ module RSpec
|
|
686
685
|
nil
|
687
686
|
end
|
688
687
|
end
|
689
|
-
# rubocop:enable Metrics/ModuleLength
|
690
688
|
|
691
689
|
include ImplementationDetails
|
692
690
|
end
|
@@ -750,6 +748,7 @@ module RSpec
|
|
750
748
|
|
751
749
|
proc.call(*args, &block)
|
752
750
|
end
|
751
|
+
ruby2_keywords(:call) if respond_to?(:ruby2_keywords, true)
|
753
752
|
end
|
754
753
|
|
755
754
|
# Represents a configured implementation. Takes into account
|
@@ -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
|
|
@@ -23,10 +26,7 @@ module RSpec
|
|
23
26
|
# handler of the object. This accounts for cases where the user has not
|
24
27
|
# correctly defined `respond_to?`, and also 1.8 which does not provide
|
25
28
|
# method handles for missing methods even if `respond_to?` is correct.
|
26
|
-
@original_implementation_callable ||= original_method ||
|
27
|
-
Proc.new do |*args, &block|
|
28
|
-
@object.__send__(:method_missing, @method_name, *args, &block)
|
29
|
-
end
|
29
|
+
@original_implementation_callable ||= original_method || method_missing_block
|
30
30
|
end
|
31
31
|
|
32
32
|
alias_method :save_original_implementation_callable!, :original_implementation_callable
|
@@ -37,6 +37,16 @@ module RSpec
|
|
37
37
|
@proxy.original_method_handle_for(method_name)
|
38
38
|
end
|
39
39
|
|
40
|
+
# @private
|
41
|
+
def method_missing_block
|
42
|
+
block = Proc.new do |*args, &b|
|
43
|
+
@object.__send__(:method_missing, @method_name, *args, &b)
|
44
|
+
end
|
45
|
+
block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
|
46
|
+
|
47
|
+
block
|
48
|
+
end
|
49
|
+
|
40
50
|
# @private
|
41
51
|
def visibility
|
42
52
|
@proxy.visibility_for(@method_name)
|
@@ -70,6 +80,14 @@ module RSpec
|
|
70
80
|
end
|
71
81
|
|
72
82
|
@method_is_proxied = true
|
83
|
+
rescue RuntimeError, TypeError => e
|
84
|
+
# TODO: drop in favor of FrozenError in ruby 2.5+
|
85
|
+
# RuntimeError (and FrozenError) for ruby 2.x
|
86
|
+
# TypeError for ruby 1.x
|
87
|
+
if (defined?(FrozenError) && e.is_a?(FrozenError)) || FROZEN_ERROR_MSG === e.message
|
88
|
+
raise ArgumentError, "Cannot proxy frozen objects, rspec-mocks relies on proxies for method stubbing and expectations."
|
89
|
+
end
|
90
|
+
raise
|
73
91
|
end
|
74
92
|
|
75
93
|
# The implementation of the proxied method. Subclasses may override this
|
@@ -83,7 +101,6 @@ module RSpec
|
|
83
101
|
|
84
102
|
# @private
|
85
103
|
def restore_original_method
|
86
|
-
return show_frozen_warning if object_singleton_class.frozen?
|
87
104
|
return unless @method_is_proxied
|
88
105
|
|
89
106
|
remove_method_from_definition_target
|
@@ -91,6 +108,14 @@ module RSpec
|
|
91
108
|
restore_original_visibility
|
92
109
|
|
93
110
|
@method_is_proxied = false
|
111
|
+
rescue RuntimeError, TypeError => e
|
112
|
+
# TODO: drop in favor of FrozenError in ruby 2.5+
|
113
|
+
# RuntimeError (and FrozenError) for ruby 2.x
|
114
|
+
# TypeError for ruby 1.x
|
115
|
+
if (defined?(FrozenError) && e.is_a?(FrozenError)) || FROZEN_ERROR_MSG === e.message
|
116
|
+
return show_frozen_warning
|
117
|
+
end
|
118
|
+
raise
|
94
119
|
end
|
95
120
|
|
96
121
|
# @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
|
-
|
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
|
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
|
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)
|
data/lib/rspec/mocks/proxy.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
RSpec::Support.require_rspec_support 'mutex'
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module Mocks
|
3
5
|
# @private
|
@@ -9,11 +11,6 @@ module RSpec
|
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
12
|
-
unless defined?(Mutex)
|
13
|
-
Support.require_rspec_support 'mutex'
|
14
|
-
Mutex = Support::Mutex
|
15
|
-
end
|
16
|
-
|
17
14
|
# @private
|
18
15
|
def ensure_implemented(*_args)
|
19
16
|
# noop for basic proxies, see VerifyingProxy for behaviour.
|
@@ -27,7 +24,7 @@ module RSpec
|
|
27
24
|
@order_group = order_group
|
28
25
|
@error_generator = ErrorGenerator.new(object)
|
29
26
|
@messages_received = []
|
30
|
-
@messages_received_mutex = Mutex.new
|
27
|
+
@messages_received_mutex = Support::Mutex.new
|
31
28
|
@options = options
|
32
29
|
@null_object = false
|
33
30
|
@method_doubles = Hash.new { |h, k| h[k] = MethodDouble.new(@object, k, self) }
|
@@ -35,15 +32,9 @@ module RSpec
|
|
35
32
|
|
36
33
|
# @private
|
37
34
|
def ensure_can_be_proxied!(object)
|
38
|
-
return unless object.is_a?(Symbol)
|
39
|
-
return if object.nil?
|
35
|
+
return unless object.is_a?(Symbol)
|
40
36
|
|
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
|
37
|
+
msg = "Cannot proxy frozen objects. Symbols such as #{object} cannot be mocked or stubbed."
|
47
38
|
raise ArgumentError, msg
|
48
39
|
end
|
49
40
|
|
@@ -198,6 +189,7 @@ module RSpec
|
|
198
189
|
@messages_received << [message, args, block]
|
199
190
|
end
|
200
191
|
end
|
192
|
+
ruby2_keywords :record_message_received if respond_to?(:ruby2_keywords, true)
|
201
193
|
|
202
194
|
# @private
|
203
195
|
def message_received(message, *args, &block)
|
data/lib/rspec/mocks/space.rb
CHANGED
@@ -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)
|
data/lib/rspec/mocks/syntax.rb
CHANGED
@@ -115,7 +115,7 @@ module RSpec
|
|
115
115
|
Matchers::Receive.new(method_name, block)
|
116
116
|
end
|
117
117
|
|
118
|
-
def receive_messages(message_return_value_hash)
|
118
|
+
def receive_messages(message_return_value_hash, &_block)
|
119
119
|
matcher = Matchers::ReceiveMessages.new(message_return_value_hash)
|
120
120
|
matcher.warn_about_block if block_given?
|
121
121
|
matcher
|
data/lib/rspec/mocks/targets.rb
CHANGED
@@ -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.
|
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
|
@@ -42,11 +42,13 @@ module RSpec
|
|
42
42
|
ensure
|
43
43
|
@__sending_message = nil
|
44
44
|
end
|
45
|
+
ruby2_keywords :__send__ if respond_to?(:ruby2_keywords, true)
|
45
46
|
$VERBOSE = old
|
46
47
|
|
47
48
|
def send(name, *args, &block)
|
48
49
|
__send__(name, *args, &block)
|
49
50
|
end
|
51
|
+
ruby2_keywords :send if respond_to?(:ruby2_keywords, true)
|
50
52
|
|
51
53
|
def initialize(doubled_module, *args)
|
52
54
|
@doubled_module = doubled_module
|
@@ -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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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|
|
data/lib/rspec/mocks/version.rb
CHANGED
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-mocks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.13.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Baker
|
8
8
|
- David Chelimsky
|
9
9
|
- Myron Marston
|
10
|
-
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain:
|
13
12
|
- |
|
@@ -45,7 +44,7 @@ cert_chain:
|
|
45
44
|
ZsVDj6a7lH3cNqtWXZxrb2wO38qV5AkYj8SQK7Hj3/Yui9myUX3crr+PdetazSqQ
|
46
45
|
F3MdtaDehhjC
|
47
46
|
-----END CERTIFICATE-----
|
48
|
-
date:
|
47
|
+
date: 2024-10-02 00:00:00.000000000 Z
|
49
48
|
dependencies:
|
50
49
|
- !ruby/object:Gem::Dependency
|
51
50
|
name: rspec-support
|
@@ -53,14 +52,14 @@ dependencies:
|
|
53
52
|
requirements:
|
54
53
|
- - "~>"
|
55
54
|
- !ruby/object:Gem::Version
|
56
|
-
version: 3.
|
55
|
+
version: 3.13.0
|
57
56
|
type: :runtime
|
58
57
|
prerelease: false
|
59
58
|
version_requirements: !ruby/object:Gem::Requirement
|
60
59
|
requirements:
|
61
60
|
- - "~>"
|
62
61
|
- !ruby/object:Gem::Version
|
63
|
-
version: 3.
|
62
|
+
version: 3.13.0
|
64
63
|
- !ruby/object:Gem::Dependency
|
65
64
|
name: diff-lcs
|
66
65
|
requirement: !ruby/object:Gem::Requirement
|
@@ -113,16 +112,22 @@ dependencies:
|
|
113
112
|
name: aruba
|
114
113
|
requirement: !ruby/object:Gem::Requirement
|
115
114
|
requirements:
|
116
|
-
- - "
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.1.0
|
118
|
+
- - "<"
|
117
119
|
- !ruby/object:Gem::Version
|
118
|
-
version: 0.
|
120
|
+
version: 3.0.0
|
119
121
|
type: :development
|
120
122
|
prerelease: false
|
121
123
|
version_requirements: !ruby/object:Gem::Requirement
|
122
124
|
requirements:
|
123
|
-
- - "
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: 1.1.0
|
128
|
+
- - "<"
|
124
129
|
- !ruby/object:Gem::Version
|
125
|
-
version: 0.
|
130
|
+
version: 3.0.0
|
126
131
|
- !ruby/object:Gem::Dependency
|
127
132
|
name: minitest
|
128
133
|
requirement: !ruby/object:Gem::Requirement
|
@@ -194,11 +199,10 @@ licenses:
|
|
194
199
|
- MIT
|
195
200
|
metadata:
|
196
201
|
bug_tracker_uri: https://github.com/rspec/rspec-mocks/issues
|
197
|
-
changelog_uri: https://github.com/rspec/rspec-mocks/blob/v3.
|
202
|
+
changelog_uri: https://github.com/rspec/rspec-mocks/blob/v3.13.2/Changelog.md
|
198
203
|
documentation_uri: https://rspec.info/documentation/
|
199
204
|
mailing_list_uri: https://groups.google.com/forum/#!forum/rspec
|
200
205
|
source_code_uri: https://github.com/rspec/rspec-mocks
|
201
|
-
post_install_message:
|
202
206
|
rdoc_options:
|
203
207
|
- "--charset=UTF-8"
|
204
208
|
require_paths:
|
@@ -214,8 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
214
218
|
- !ruby/object:Gem::Version
|
215
219
|
version: '0'
|
216
220
|
requirements: []
|
217
|
-
rubygems_version: 3.
|
218
|
-
signing_key:
|
221
|
+
rubygems_version: 3.6.0.dev
|
219
222
|
specification_version: 4
|
220
|
-
summary: rspec-mocks-3.
|
223
|
+
summary: rspec-mocks-3.13.2
|
221
224
|
test_files: []
|
metadata.gz.sig
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
�
|
1
|
+
_�,�{6^Mf��JP�ق^��9+��K�)i߉&:�6�f�+��u�*��V1�0�p2��w�{�5�ӂ�F֎�)TM@�PE²f��&���:�U;���WdeJ�S=C79��$դ#7YX��E�\���H�փp/�<�D�7���� �i��R�u��Ԭ
|
2
|
+
�6�[4��k����&�Ҹ=Oߣ �`\���-m4?2�J�gUNb�R����έ4�S��s�?VP�k�p�B<�1�5�`��4���?_=��g�$x<$�B�CW*<�����V?KϜeA�1�
|
3
|
+
��A;���N|a������py�
|