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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/Changelog.md +96 -1
- data/README.md +1 -1
- 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/argument_list_matcher.rb +20 -3
- 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 +4 -2
- data/lib/rspec/mocks/matchers/receive_message_chain.rb +2 -2
- data/lib/rspec/mocks/matchers/receive_messages.rb +1 -1
- data/lib/rspec/mocks/message_expectation.rb +74 -5
- data/lib/rspec/mocks/method_double.rb +22 -1
- 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 +9 -8
- data/lib/rspec/mocks/space.rb +1 -1
- data/lib/rspec/mocks/targets.rb +1 -1
- data/lib/rspec/mocks/verifying_double.rb +4 -10
- 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 +13 -13
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ac306bd185750c3017ee678b47a8049e734c0442b6cef60e8e7a04aa13c29c4
|
4
|
+
data.tar.gz: bde012659ef5fb279c0dee84a6788ba3a58156bfca1d3bdf934c99e6b96c26dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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 [](https://github.com/rspec/rspec-mocks/actions) [](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
|
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
|
@@ -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]
|
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?(*
|
58
|
-
|
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
|
-
|
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,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
|
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
|
23
|
+
def matcher_name
|
24
24
|
"receive_message_chain"
|
25
25
|
end
|
26
26
|
|
@@ -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
|
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
|
-
|
101
|
-
original.call(*args, &
|
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
|
-
|
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
@@ -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)
|
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
|
|
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/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
|
@@ -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, $
|
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
|
-
|
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
|
@@ -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,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-mocks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
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:
|
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.
|
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.
|
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
|
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
|
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:
|
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:
|
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.
|
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.
|
217
|
+
rubygems_version: 3.4.1
|
218
218
|
signing_key:
|
219
219
|
specification_version: 4
|
220
|
-
summary: rspec-mocks-3.
|
220
|
+
summary: rspec-mocks-3.12.5
|
221
221
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|