rspec-mocks 3.5.0 → 3.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Changelog.md +83 -1
- data/README.md +21 -3
- data/lib/rspec/mocks/any_instance/chain.rb +1 -0
- data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +1 -5
- data/lib/rspec/mocks/any_instance/expectation_chain.rb +7 -5
- data/lib/rspec/mocks/any_instance/recorder.rb +1 -1
- data/lib/rspec/mocks/any_instance/stub_chain.rb +9 -5
- data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +1 -6
- data/lib/rspec/mocks/argument_matchers.rb +3 -1
- data/lib/rspec/mocks/configuration.rb +7 -0
- data/lib/rspec/mocks/error_generator.rb +11 -11
- data/lib/rspec/mocks/example_methods.rb +14 -2
- data/lib/rspec/mocks/instance_method_stasher.rb +11 -0
- data/lib/rspec/mocks/matchers/have_received.rb +5 -1
- data/lib/rspec/mocks/message_expectation.rb +17 -6
- data/lib/rspec/mocks/method_double.rb +3 -3
- data/lib/rspec/mocks/method_reference.rb +9 -9
- data/lib/rspec/mocks/mutate_const.rb +4 -0
- data/lib/rspec/mocks/proxy.rb +34 -20
- data/lib/rspec/mocks/test_double.rb +2 -1
- data/lib/rspec/mocks/verifying_proxy.rb +7 -0
- data/lib/rspec/mocks/version.rb +1 -1
- metadata +14 -11
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f53d2fe5ab69778d6528b80a08aaa48869a527c5185f715671c0d48beecf5db4
|
4
|
+
data.tar.gz: 8e06d4be6fbc3dec6cbbdf75d141638db33653579fcd95b4869cb41b97afb4e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6863b589a173e3985263e2b49c797389e7db68912df5f6f294f23833d66cbeb72b10b9b800cca08383322f1b1775b99f7514878663b715b48d4d6e39582b4836
|
7
|
+
data.tar.gz: 320ec537f1f7708bd0fb5317ab3878cb569f2a9dbd676b8b8512f36ece73f5efc0d9f7d85bb8b6b30ac145cc5ff3f10d13212897c19e6559a475526703325e1d
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/Changelog.md
CHANGED
@@ -1,3 +1,84 @@
|
|
1
|
+
### 3.9.0 / 2019-10-07
|
2
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.8.2...v3.9.0)
|
3
|
+
|
4
|
+
Enhancements:
|
5
|
+
|
6
|
+
* Improve thread safety of message expectations by using Mutex to prevent
|
7
|
+
deadlocking errors. (Ry Biesemeyer, #1236)
|
8
|
+
* Add the ability to use `time` as an alias for `times`. For example:
|
9
|
+
`expect(Class).to receive(:method).exactly(1).time`.
|
10
|
+
(Pistos, Benoit Tigeot, #1271)
|
11
|
+
|
12
|
+
### 3.8.2 / 2019-10-02
|
13
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.8.1...v3.8.2)
|
14
|
+
|
15
|
+
* Allow `array_including` argument matchers to be nested.
|
16
|
+
(Emmanuel Delmas, #1291)
|
17
|
+
|
18
|
+
### 3.8.1 / 2019-06-13
|
19
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.8.0...v3.8.1)
|
20
|
+
|
21
|
+
Bug Fixes:
|
22
|
+
|
23
|
+
* Ensure stubbing methods does not change their visibility.
|
24
|
+
(Kevin Boschert, #1277)
|
25
|
+
|
26
|
+
### 3.8.0 / 2018-08-04
|
27
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.7.0...v3.8.0)
|
28
|
+
|
29
|
+
Bug Fixes:
|
30
|
+
|
31
|
+
* Issue error when encountering invalid "counted" negative message expectations.
|
32
|
+
(Sergiy Yarinovskiy, #1212)
|
33
|
+
* Ensure `allow_any_instance_of` and `expect_any_instance_of` can be temporarily
|
34
|
+
supressed. (Jon Rowe, #1228)
|
35
|
+
* Ensure `expect_any_instance_of(double).to_not have_received(:some_method)`
|
36
|
+
fails gracefully (as its not supported) rather than issuing a `NoMethodError`.
|
37
|
+
(Maxim Krizhanovsky, #1231)
|
38
|
+
|
39
|
+
### 3.7.0 / 2017-10-17
|
40
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.6.0...v3.7.0)
|
41
|
+
|
42
|
+
Enhancements:
|
43
|
+
|
44
|
+
* Improve compatibility with `--enable-frozen-string-literal` option
|
45
|
+
on Ruby 2.3+. (Pat Allan, #1165)
|
46
|
+
|
47
|
+
Bug Fixes:
|
48
|
+
|
49
|
+
* Fix `hash_including` and `hash_excluding` so that they work against
|
50
|
+
subclasses of `Hash`. (Aaron Rosenberg, #1167)
|
51
|
+
|
52
|
+
### 3.6.0 / 2017-05-04
|
53
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.6.0.beta2...v3.6.0)
|
54
|
+
|
55
|
+
Bug Fixes:
|
56
|
+
|
57
|
+
* Fix "instance variable @color not initialized" warning when using
|
58
|
+
rspec-mocks without rspec-core. (Myron Marston, #1142)
|
59
|
+
* Restore aliased module methods properly when stubbing on 1.8.7.
|
60
|
+
(Samuel Giddins, #1144)
|
61
|
+
* Allow a message chain expectation to be constrained by argument(s).
|
62
|
+
(Jon Rowe, #1156)
|
63
|
+
|
64
|
+
### 3.6.0.beta2 / 2016-12-12
|
65
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.6.0.beta1...v3.6.0.beta2)
|
66
|
+
|
67
|
+
Enhancements:
|
68
|
+
|
69
|
+
* Add new `without_partial_double_verification { }` API that lets you
|
70
|
+
temporarily turn off partial double verification for an example.
|
71
|
+
(Jon Rowe, #1104)
|
72
|
+
|
73
|
+
### 3.6.0.beta1 / 2016-10-09
|
74
|
+
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.5.0...v3.6.0.beta1)
|
75
|
+
|
76
|
+
Bug Fixes:
|
77
|
+
|
78
|
+
* Return the test double instance form `#freeze` (Alessandro Berardi, #1109)
|
79
|
+
* Allow the special logic for stubbing `new` to work when `<Class>.method` has
|
80
|
+
been redefined. (Proby, #1119)
|
81
|
+
|
1
82
|
### 3.5.0 / 2016-07-01
|
2
83
|
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.5.0.beta4...v3.5.0)
|
3
84
|
|
@@ -850,7 +931,8 @@ Bug fixes
|
|
850
931
|
* Fix `should_receive` so that when it is called on an `as_null_object`
|
851
932
|
double with no implementation, and there is a previous explicit stub
|
852
933
|
for the same method, the explicit stub remains (rather than being
|
853
|
-
|
934
|
+
overridden with the null object implementation--`return self`). (Myron
|
935
|
+
Marston)
|
854
936
|
|
855
937
|
### 2.11.0 / 2012-07-07
|
856
938
|
[Full Changelog](http://github.com/rspec/rspec-mocks/compare/v2.10.1...v2.11.0)
|
data/README.md
CHANGED
@@ -13,7 +13,7 @@ RSpec repos as well. Add the following to your `Gemfile`:
|
|
13
13
|
|
14
14
|
```ruby
|
15
15
|
%w[rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib|
|
16
|
-
gem lib, :git => "
|
16
|
+
gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => 'master'
|
17
17
|
end
|
18
18
|
```
|
19
19
|
## Contributing
|
@@ -101,6 +101,21 @@ that iterates through them:
|
|
101
101
|
order.calculate_total_price(double(:price => 1.99), double(:price => 2.99))
|
102
102
|
```
|
103
103
|
|
104
|
+
### Stubbing a chain of methods
|
105
|
+
|
106
|
+
You can use `receive_message_chain` in place of `receive` to stub a chain of messages:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
allow(double).to receive_message_chain("foo.bar") { :baz }
|
110
|
+
allow(double).to receive_message_chain(:foo, :bar => :baz)
|
111
|
+
allow(double).to receive_message_chain(:foo, :bar) { :baz }
|
112
|
+
|
113
|
+
# Given any of the above forms:
|
114
|
+
double.foo.bar # => :baz
|
115
|
+
```
|
116
|
+
|
117
|
+
Chains can be arbitrarily long, which makes it quite painless to violate the Law of Demeter in violent ways, so you should consider any use of `receive_message_chain` a code smell. Even though not all code smells indicate real problems (think fluent interfaces), `receive_message_chain` still results in brittle examples. For example, if you write `allow(foo).to receive_message_chain(:bar, :baz => 37)` in a spec and then the implementation calls `foo.baz.bar`, the stub will not work.
|
118
|
+
|
104
119
|
## Consecutive return values
|
105
120
|
|
106
121
|
When a stub might be invoked more than once, you can provide additional
|
@@ -242,7 +257,7 @@ expect(double).to receive(:msg).with("B", 2, 4)
|
|
242
257
|
## Argument Matchers
|
243
258
|
|
244
259
|
Arguments that are passed to `with` are compared with actual arguments
|
245
|
-
received using
|
260
|
+
received using ===. In cases in which you want to specify things about the
|
246
261
|
arguments rather than the arguments themselves, you can use any of the
|
247
262
|
matchers that ship with rspec-expectations. They don't all make syntactic
|
248
263
|
sense (they were primarily designed for use with RSpec::Expectations), but
|
@@ -270,12 +285,15 @@ expect(double).to receive(:msg).with(hash_excluding(:a => 5)) # first arg is a h
|
|
270
285
|
```ruby
|
271
286
|
expect(double).to receive(:msg).once
|
272
287
|
expect(double).to receive(:msg).twice
|
288
|
+
expect(double).to receive(:msg).exactly(n).time
|
273
289
|
expect(double).to receive(:msg).exactly(n).times
|
274
290
|
expect(double).to receive(:msg).at_least(:once)
|
275
291
|
expect(double).to receive(:msg).at_least(:twice)
|
292
|
+
expect(double).to receive(:msg).at_least(n).time
|
276
293
|
expect(double).to receive(:msg).at_least(n).times
|
277
294
|
expect(double).to receive(:msg).at_most(:once)
|
278
295
|
expect(double).to receive(:msg).at_most(:twice)
|
296
|
+
expect(double).to receive(:msg).at_most(n).time
|
279
297
|
expect(double).to receive(:msg).at_most(n).times
|
280
298
|
```
|
281
299
|
|
@@ -312,7 +330,7 @@ expect(double).to receive(:msg).and_return(value)
|
|
312
330
|
expect(double).to receive(:msg).exactly(3).times.and_return(value1, value2, value3)
|
313
331
|
# returns value1 the first time, value2 the second, etc
|
314
332
|
expect(double).to receive(:msg).and_raise(error)
|
315
|
-
# error can be an instantiated object or a class
|
333
|
+
# `error` can be an instantiated object (e.g. `StandardError.new(some_arg)`) or a class (e.g. `StandardError`)
|
316
334
|
# if it is a class, it must be instantiable with no args
|
317
335
|
expect(double).to receive(:msg).and_throw(:msg)
|
318
336
|
expect(double).to receive(:msg).and_yield(values, to, yield)
|
@@ -35,12 +35,14 @@ module RSpec
|
|
35
35
|
me
|
36
36
|
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
:with => [nil],
|
38
|
+
ExpectationInvocationOrder =
|
39
|
+
{
|
41
40
|
:and_return => [:with, nil],
|
42
|
-
:and_raise => [:with, nil]
|
43
|
-
}
|
41
|
+
:and_raise => [:with, nil],
|
42
|
+
}.freeze
|
43
|
+
|
44
|
+
def invocation_order
|
45
|
+
ExpectationInvocationOrder
|
44
46
|
end
|
45
47
|
end
|
46
48
|
end
|
@@ -242,7 +242,7 @@ module RSpec
|
|
242
242
|
def observe!(method_name)
|
243
243
|
allow_no_prepended_module_definition_of(method_name)
|
244
244
|
|
245
|
-
if RSpec::Mocks.configuration.verify_partial_doubles?
|
245
|
+
if RSpec::Mocks.configuration.verify_partial_doubles? && !Mocks.configuration.temporarily_suppress_partial_double_verification
|
246
246
|
unless public_protected_or_private_method_defined?(method_name)
|
247
247
|
AnyInstance.error_generator.raise_does_not_implement_error(@klass, method_name)
|
248
248
|
end
|
@@ -25,20 +25,24 @@ module RSpec
|
|
25
25
|
stub
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
:with => [nil],
|
28
|
+
InvocationOrder =
|
29
|
+
{
|
31
30
|
:and_return => [:with, nil],
|
32
31
|
:and_raise => [:with, nil],
|
33
32
|
:and_yield => [:with, :and_yield, nil],
|
34
33
|
:and_throw => [:with, nil],
|
35
34
|
:and_call_original => [:with, nil],
|
36
35
|
:and_wrap_original => [:with, nil]
|
37
|
-
}
|
36
|
+
}.freeze
|
37
|
+
|
38
|
+
EmptyInvocationOrder = {}.freeze
|
39
|
+
|
40
|
+
def invocation_order
|
41
|
+
InvocationOrder
|
38
42
|
end
|
39
43
|
|
40
44
|
def verify_invocation_order(rspec_method_name, *_args, &_block)
|
41
|
-
return if invocation_order[
|
45
|
+
return if invocation_order.fetch(rspec_method_name, [nil]).include?(last_message)
|
42
46
|
raise NoMethodError, "Undefined method #{rspec_method_name}"
|
43
47
|
end
|
44
48
|
end
|
@@ -116,7 +116,7 @@ module RSpec
|
|
116
116
|
|
117
117
|
# @private
|
118
118
|
def self.anythingize_lonely_keys(*args)
|
119
|
-
hash = args.last
|
119
|
+
hash = Hash === args.last ? args.delete_at(-1) : {}
|
120
120
|
args.each { | arg | hash[arg] = AnyArgMatcher::INSTANCE }
|
121
121
|
hash
|
122
122
|
end
|
@@ -241,6 +241,8 @@ module RSpec
|
|
241
241
|
RSpec::Support::FuzzyMatcher.values_match?(expected_element, actual_element)
|
242
242
|
end
|
243
243
|
end
|
244
|
+
rescue NoMethodError
|
245
|
+
false
|
244
246
|
end
|
245
247
|
|
246
248
|
def description
|
@@ -8,6 +8,8 @@ module RSpec
|
|
8
8
|
@verify_doubled_constant_names = false
|
9
9
|
@transfer_nested_constants = false
|
10
10
|
@verify_partial_doubles = false
|
11
|
+
@temporarily_suppress_partial_double_verification = false
|
12
|
+
@color = false
|
11
13
|
end
|
12
14
|
|
13
15
|
# Sets whether RSpec will warn, ignore, or fail a test when
|
@@ -153,6 +155,11 @@ module RSpec
|
|
153
155
|
@verify_partial_doubles
|
154
156
|
end
|
155
157
|
|
158
|
+
# @private
|
159
|
+
# Used to track wether we are temporarily suppressing verifying partial
|
160
|
+
# doubles with `without_partial_double_verification { ... }`
|
161
|
+
attr_accessor :temporarily_suppress_partial_double_verification
|
162
|
+
|
156
163
|
if ::RSpec.respond_to?(:configuration)
|
157
164
|
def color?
|
158
165
|
::RSpec.configuration.color_enabled?
|
@@ -57,10 +57,10 @@ module RSpec
|
|
57
57
|
|
58
58
|
# @private
|
59
59
|
def raise_missing_default_stub_error(expectation, args_for_multiple_calls)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
__raise(
|
61
|
+
error_message(expectation, args_for_multiple_calls) +
|
62
|
+
"\n Please stub a default value first if message might be received with other args as well. \n"
|
63
|
+
)
|
64
64
|
end
|
65
65
|
|
66
66
|
# @private
|
@@ -69,10 +69,10 @@ module RSpec
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def default_error_message(expectation, expected_args, actual_args)
|
72
|
-
"#{intro} received #{expectation.message.inspect} #{unexpected_arguments_message(expected_args, actual_args)}"
|
72
|
+
"#{intro} received #{expectation.message.inspect} #{unexpected_arguments_message(expected_args, actual_args)}".dup
|
73
73
|
end
|
74
74
|
|
75
|
-
# rubocop:disable
|
75
|
+
# rubocop:disable Metrics/ParameterLists
|
76
76
|
# @private
|
77
77
|
def raise_expectation_error(message, expected_received_count, argument_list_matcher,
|
78
78
|
actual_received_count, expectation_count_type, args,
|
@@ -81,20 +81,20 @@ module RSpec
|
|
81
81
|
received_part = received_part_of_expectation_error(actual_received_count, args)
|
82
82
|
__raise "(#{intro(:unwrapped)}).#{message}#{format_args(args)}\n #{expected_part}\n #{received_part}", backtrace_line, source_id
|
83
83
|
end
|
84
|
-
# rubocop:enable
|
84
|
+
# rubocop:enable Metrics/ParameterLists
|
85
85
|
|
86
86
|
# @private
|
87
87
|
def raise_unimplemented_error(doubled_module, method_name, object)
|
88
88
|
message = case object
|
89
89
|
when InstanceVerifyingDouble
|
90
|
-
"the %s class does not implement the instance method: %s" <<
|
90
|
+
"the %s class does not implement the instance method: %s".dup <<
|
91
91
|
if ObjectMethodReference.for(doubled_module, method_name).implemented?
|
92
92
|
". Perhaps you meant to use `class_double` instead?"
|
93
93
|
else
|
94
94
|
""
|
95
95
|
end
|
96
96
|
when ClassVerifyingDouble
|
97
|
-
"the %s class does not implement the class method: %s" <<
|
97
|
+
"the %s class does not implement the class method: %s".dup <<
|
98
98
|
if InstanceMethodReference.for(doubled_module, method_name).implemented?
|
99
99
|
". Perhaps you meant to use `instance_double` instead?"
|
100
100
|
else
|
@@ -214,8 +214,8 @@ module RSpec
|
|
214
214
|
|
215
215
|
def expectation_on_nil_message(method_name)
|
216
216
|
"An expectation of `:#{method_name}` was set on `nil`. " \
|
217
|
-
"To allow expectations on `nil` and suppress this message, set `
|
218
|
-
"To disallow expectations on `nil`, set `
|
217
|
+
"To allow expectations on `nil` and suppress this message, set `RSpec::Mocks.configuration.allow_message_expectations_on_nil` to `true`. " \
|
218
|
+
"To disallow expectations on `nil`, set `RSpec::Mocks.configuration.allow_message_expectations_on_nil` to `false`"
|
219
219
|
end
|
220
220
|
|
221
221
|
# @private
|
@@ -282,6 +282,18 @@ module RSpec
|
|
282
282
|
Matchers::HaveReceived.new(method_name, &block)
|
283
283
|
end
|
284
284
|
|
285
|
+
# Turns off the verifying of partial doubles for the duration of the
|
286
|
+
# block, this is useful in situations where methods are defined at run
|
287
|
+
# time and you wish to define stubs for them but not turn off partial
|
288
|
+
# doubles for the entire run suite. (e.g. view specs in rspec-rails).
|
289
|
+
def without_partial_double_verification
|
290
|
+
original_state = Mocks.configuration.temporarily_suppress_partial_double_verification
|
291
|
+
Mocks.configuration.temporarily_suppress_partial_double_verification = true
|
292
|
+
yield
|
293
|
+
ensure
|
294
|
+
Mocks.configuration.temporarily_suppress_partial_double_verification = original_state
|
295
|
+
end
|
296
|
+
|
285
297
|
# @method expect
|
286
298
|
# Used to wrap an object in preparation for setting a mock expectation
|
287
299
|
# on it.
|
@@ -380,7 +392,7 @@ module RSpec
|
|
380
392
|
def self.included(klass)
|
381
393
|
klass.class_exec do
|
382
394
|
# This gets mixed in so that if `RSpec::Matchers` is included in
|
383
|
-
# `klass` later,
|
395
|
+
# `klass` later, its definition of `expect` will take precedence.
|
384
396
|
include ExpectHost unless method_defined?(:expect)
|
385
397
|
end
|
386
398
|
end
|
@@ -388,7 +400,7 @@ module RSpec
|
|
388
400
|
# @private
|
389
401
|
def self.extended(object)
|
390
402
|
# This gets extended in so that if `RSpec::Matchers` is included in
|
391
|
-
# `klass` later,
|
403
|
+
# `klass` later, its definition of `expect` will take precedence.
|
392
404
|
object.extend ExpectHost unless object.respond_to?(:expect)
|
393
405
|
end
|
394
406
|
|
@@ -128,6 +128,17 @@ module RSpec
|
|
128
128
|
# Hence, we verify that the owner actually has the method defined.
|
129
129
|
# If the given owner does not have the method defined, we assume
|
130
130
|
# that the method is actually owned by @klass.
|
131
|
+
#
|
132
|
+
# On 1.8, aliased methods can also report the wrong owner. Example:
|
133
|
+
# module M
|
134
|
+
# def a; end
|
135
|
+
# module_function :a
|
136
|
+
# alias b a
|
137
|
+
# module_function :b
|
138
|
+
# end
|
139
|
+
# The owner of M.b is the raw Module object, instead of the expected
|
140
|
+
# singleton class of the module
|
141
|
+
return true if RUBY_VERSION < '1.9' && owner == @object
|
131
142
|
owner == @klass || !(method_defined_on_klass?(owner))
|
132
143
|
end
|
133
144
|
end
|
@@ -5,7 +5,7 @@ module RSpec
|
|
5
5
|
class HaveReceived
|
6
6
|
include Matcher
|
7
7
|
|
8
|
-
COUNT_CONSTRAINTS = %w[exactly at_least at_most times once twice thrice]
|
8
|
+
COUNT_CONSTRAINTS = %w[exactly at_least at_most times time once twice thrice]
|
9
9
|
ARGS_CONSTRAINTS = %w[with]
|
10
10
|
CONSTRAINTS = COUNT_CONSTRAINTS + ARGS_CONSTRAINTS + %w[ordered]
|
11
11
|
|
@@ -76,6 +76,10 @@ module RSpec
|
|
76
76
|
disallow("expect_any_instance_of")
|
77
77
|
end
|
78
78
|
|
79
|
+
def setup_any_instance_negative_expectation(_subject, &_block)
|
80
|
+
disallow("expect_any_instance_of")
|
81
|
+
end
|
82
|
+
|
79
83
|
private
|
80
84
|
|
81
85
|
def disallow(type, reason="")
|
@@ -1,3 +1,5 @@
|
|
1
|
+
RSpec::Support.require_rspec_support 'mutex'
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module Mocks
|
3
5
|
# A message expectation that only allows concrete return values to be set
|
@@ -236,6 +238,7 @@ module RSpec
|
|
236
238
|
self.inner_implementation_action = block
|
237
239
|
self
|
238
240
|
end
|
241
|
+
alias time times
|
239
242
|
|
240
243
|
# Expect a message not to be received at all.
|
241
244
|
#
|
@@ -330,7 +333,7 @@ module RSpec
|
|
330
333
|
def ordered(&block)
|
331
334
|
if type == :stub
|
332
335
|
RSpec.warning(
|
333
|
-
"`allow(...).to receive(..).ordered` is not supported and will" \
|
336
|
+
"`allow(...).to receive(..).ordered` is not supported and will " \
|
334
337
|
"have no effect, use `and_return(*ordered_values)` instead."
|
335
338
|
)
|
336
339
|
end
|
@@ -357,6 +360,7 @@ module RSpec
|
|
357
360
|
# some collaborators it delegates to for this stuff but for now this was
|
358
361
|
# the simplest way to split the public from private stuff to make it
|
359
362
|
# easier to publish the docs for the APIs we want published.
|
363
|
+
# rubocop:disable Metrics/ModuleLength
|
360
364
|
module ImplementationDetails
|
361
365
|
attr_accessor :error_generator, :implementation
|
362
366
|
attr_reader :message
|
@@ -367,7 +371,7 @@ module RSpec
|
|
367
371
|
# @private
|
368
372
|
attr_reader :type
|
369
373
|
|
370
|
-
# rubocop:disable
|
374
|
+
# rubocop:disable Metrics/ParameterLists
|
371
375
|
def initialize(error_generator, expectation_ordering, expected_from, method_double,
|
372
376
|
type=:expectation, opts={}, &implementation_block)
|
373
377
|
@type = type
|
@@ -378,6 +382,7 @@ module RSpec
|
|
378
382
|
@orig_object = @method_double.object
|
379
383
|
@message = @method_double.method_name
|
380
384
|
@actual_received_count = 0
|
385
|
+
@actual_received_count_write_mutex = Support::Mutex.new
|
381
386
|
@expected_received_count = type == :expectation ? 1 : :any
|
382
387
|
@argument_list_matcher = ArgumentListMatcher::MATCH_ALL
|
383
388
|
@order_group = expectation_ordering
|
@@ -395,7 +400,7 @@ module RSpec
|
|
395
400
|
@implementation = Implementation.new
|
396
401
|
self.inner_implementation_action = implementation_block
|
397
402
|
end
|
398
|
-
# rubocop:enable
|
403
|
+
# rubocop:enable Metrics/ParameterLists
|
399
404
|
|
400
405
|
def expected_args
|
401
406
|
@argument_list_matcher.expected_args
|
@@ -536,7 +541,9 @@ module RSpec
|
|
536
541
|
end
|
537
542
|
|
538
543
|
def increase_actual_received_count!
|
539
|
-
@
|
544
|
+
@actual_received_count_write_mutex.synchronize do
|
545
|
+
@actual_received_count += 1
|
546
|
+
end
|
540
547
|
end
|
541
548
|
|
542
549
|
private
|
@@ -567,7 +574,9 @@ module RSpec
|
|
567
574
|
parent_stub.invoke(nil, *args, &block)
|
568
575
|
end
|
569
576
|
ensure
|
570
|
-
@
|
577
|
+
@actual_received_count_write_mutex.synchronize do
|
578
|
+
@actual_received_count += increment
|
579
|
+
end
|
571
580
|
end
|
572
581
|
|
573
582
|
def has_been_invoked?
|
@@ -581,6 +590,7 @@ module RSpec
|
|
581
590
|
end
|
582
591
|
|
583
592
|
def set_expected_received_count(relativity, n)
|
593
|
+
raise "`count` is not supported with negative message expectations" if negative?
|
584
594
|
@at_least = (relativity == :at_least)
|
585
595
|
@at_most = (relativity == :at_most)
|
586
596
|
@exactly = (relativity == :exactly)
|
@@ -625,6 +635,7 @@ module RSpec
|
|
625
635
|
nil
|
626
636
|
end
|
627
637
|
end
|
638
|
+
# rubocop:enable Metrics/ModuleLength
|
628
639
|
|
629
640
|
include ImplementationDetails
|
630
641
|
end
|
@@ -650,7 +661,7 @@ module RSpec
|
|
650
661
|
@error_generator.raise_wrong_arity_error(args, block_signature)
|
651
662
|
end
|
652
663
|
|
653
|
-
value = @eval_context ? @eval_context.instance_exec(*args, &block) :
|
664
|
+
value = @eval_context ? @eval_context.instance_exec(*args, &block) : yield(*args)
|
654
665
|
end
|
655
666
|
value
|
656
667
|
end
|
@@ -59,7 +59,7 @@ module RSpec
|
|
59
59
|
return if @method_is_proxied
|
60
60
|
|
61
61
|
save_original_implementation_callable!
|
62
|
-
definition_target.class_exec(self, method_name, visibility) do |method_double, method_name, visibility|
|
62
|
+
definition_target.class_exec(self, method_name, @original_visibility || visibility) do |method_double, method_name, visibility|
|
63
63
|
define_method(method_name) do |*args, &block|
|
64
64
|
method_double.proxy_method_invoked(self, *args, &block)
|
65
65
|
end
|
@@ -207,8 +207,8 @@ module RSpec
|
|
207
207
|
|
208
208
|
# In Ruby 2.0.0 and above prepend will alter the method lookup chain.
|
209
209
|
# We use an object's singleton class to define method doubles upon,
|
210
|
-
# however if the object has had
|
211
|
-
#
|
210
|
+
# however if the object has had its singleton class (as opposed to
|
211
|
+
# its actual class) prepended too then the the method lookup chain
|
212
212
|
# will look in the prepended module first, **before** the singleton
|
213
213
|
# class.
|
214
214
|
#
|
@@ -64,14 +64,6 @@ module RSpec
|
|
64
64
|
:public
|
65
65
|
end
|
66
66
|
|
67
|
-
private
|
68
|
-
|
69
|
-
def original_method
|
70
|
-
@object_reference.when_loaded do |m|
|
71
|
-
self.defined? && find_method(m)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
67
|
def self.instance_method_visibility_for(klass, method_name)
|
76
68
|
if klass.public_method_defined?(method_name)
|
77
69
|
:public
|
@@ -107,6 +99,14 @@ module RSpec
|
|
107
99
|
|
108
100
|
return :public if visible
|
109
101
|
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def original_method
|
106
|
+
@object_reference.when_loaded do |m|
|
107
|
+
self.defined? && find_method(m)
|
108
|
+
end
|
109
|
+
end
|
110
110
|
end
|
111
111
|
|
112
112
|
# @private
|
@@ -189,7 +189,7 @@ module RSpec
|
|
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
|
+
::RSpec::Support.method_handle_for(klass, :new).owner == ::Class
|
193
193
|
end
|
194
194
|
|
195
195
|
def with_signature
|
@@ -105,6 +105,10 @@ module RSpec
|
|
105
105
|
# so you can stub constants in other contexts (e.g. helper
|
106
106
|
# classes).
|
107
107
|
def self.stub(constant_name, value, options={})
|
108
|
+
unless String === constant_name
|
109
|
+
raise ArgumentError, "`stub_const` requires a String, but you provided a #{constant_name.class.name}"
|
110
|
+
end
|
111
|
+
|
108
112
|
mutator = if recursive_const_defined?(constant_name, &raise_on_invalid_const)
|
109
113
|
DefinedConstantReplacer
|
110
114
|
else
|
data/lib/rspec/mocks/proxy.rb
CHANGED
@@ -2,12 +2,18 @@ module RSpec
|
|
2
2
|
module Mocks
|
3
3
|
# @private
|
4
4
|
class Proxy
|
5
|
+
# @private
|
5
6
|
SpecificMessage = Struct.new(:object, :message, :args) do
|
6
7
|
def ==(expectation)
|
7
8
|
expectation.orig_object == object && expectation.matches?(message, *args)
|
8
9
|
end
|
9
10
|
end
|
10
11
|
|
12
|
+
unless defined?(Mutex)
|
13
|
+
Support.require_rspec_support 'mutex'
|
14
|
+
Mutex = Support::Mutex
|
15
|
+
end
|
16
|
+
|
11
17
|
# @private
|
12
18
|
def ensure_implemented(*_args)
|
13
19
|
# noop for basic proxies, see VerifyingProxy for behaviour.
|
@@ -19,6 +25,7 @@ module RSpec
|
|
19
25
|
@order_group = order_group
|
20
26
|
@error_generator = ErrorGenerator.new(object)
|
21
27
|
@messages_received = []
|
28
|
+
@messages_received_mutex = Mutex.new
|
22
29
|
@options = options
|
23
30
|
@null_object = false
|
24
31
|
@method_doubles = Hash.new { |h, k| h[k] = MethodDouble.new(@object, k, self) }
|
@@ -89,27 +96,31 @@ module RSpec
|
|
89
96
|
@error_generator.raise_expectation_on_unstubbed_method(expected_method_name)
|
90
97
|
end
|
91
98
|
|
92
|
-
@
|
93
|
-
|
99
|
+
@messages_received_mutex.synchronize do
|
100
|
+
@messages_received.each do |(actual_method_name, args, received_block)|
|
101
|
+
next unless expectation.matches?(actual_method_name, *args)
|
94
102
|
|
95
|
-
|
96
|
-
|
103
|
+
expectation.safe_invoke(nil)
|
104
|
+
block.call(*args, &received_block) if block
|
105
|
+
end
|
97
106
|
end
|
98
107
|
end
|
99
108
|
|
100
109
|
# @private
|
101
110
|
def check_for_unexpected_arguments(expectation)
|
102
|
-
|
111
|
+
@messages_received_mutex.synchronize do
|
112
|
+
return if @messages_received.empty?
|
103
113
|
|
104
|
-
|
114
|
+
return if @messages_received.any? { |method_name, args, _| expectation.matches?(method_name, *args) }
|
105
115
|
|
106
|
-
|
107
|
-
|
108
|
-
|
116
|
+
name_but_not_args, others = @messages_received.partition do |(method_name, args, _)|
|
117
|
+
expectation.matches_name_but_not_args(method_name, *args)
|
118
|
+
end
|
109
119
|
|
110
|
-
|
120
|
+
return if name_but_not_args.empty? && !others.empty?
|
111
121
|
|
112
|
-
|
122
|
+
expectation.raise_unexpected_message_args_error(name_but_not_args.map { |args| args[1] })
|
123
|
+
end
|
113
124
|
end
|
114
125
|
|
115
126
|
# @private
|
@@ -140,17 +151,23 @@ module RSpec
|
|
140
151
|
|
141
152
|
# @private
|
142
153
|
def reset
|
143
|
-
@
|
154
|
+
@messages_received_mutex.synchronize do
|
155
|
+
@messages_received.clear
|
156
|
+
end
|
144
157
|
end
|
145
158
|
|
146
159
|
# @private
|
147
160
|
def received_message?(method_name, *args, &block)
|
148
|
-
@
|
161
|
+
@messages_received_mutex.synchronize do
|
162
|
+
@messages_received.any? { |array| array == [method_name, args, block] }
|
163
|
+
end
|
149
164
|
end
|
150
165
|
|
151
166
|
# @private
|
152
167
|
def messages_arg_list
|
153
|
-
@
|
168
|
+
@messages_received_mutex.synchronize do
|
169
|
+
@messages_received.map { |_, args, _| args }
|
170
|
+
end
|
154
171
|
end
|
155
172
|
|
156
173
|
# @private
|
@@ -161,7 +178,9 @@ module RSpec
|
|
161
178
|
# @private
|
162
179
|
def record_message_received(message, *args, &block)
|
163
180
|
@order_group.invoked SpecificMessage.new(object, message, args)
|
164
|
-
@
|
181
|
+
@messages_received_mutex.synchronize do
|
182
|
+
@messages_received << [message, args, block]
|
183
|
+
end
|
165
184
|
end
|
166
185
|
|
167
186
|
# @private
|
@@ -439,11 +458,6 @@ module RSpec
|
|
439
458
|
super
|
440
459
|
end
|
441
460
|
|
442
|
-
def add_negative_message_expectation(location, method_name, &implementation)
|
443
|
-
warn_or_raise!(method_name)
|
444
|
-
super
|
445
|
-
end
|
446
|
-
|
447
461
|
def add_stub(method_name, opts={}, &implementation)
|
448
462
|
warn_or_raise!(method_name)
|
449
463
|
super
|
@@ -44,7 +44,7 @@ module RSpec
|
|
44
44
|
|
45
45
|
# @private
|
46
46
|
def to_s
|
47
|
-
inspect.
|
47
|
+
inspect.tr('<', '[').tr('>', ']')
|
48
48
|
end
|
49
49
|
|
50
50
|
# @private
|
@@ -66,6 +66,7 @@ module RSpec
|
|
66
66
|
# doubles.
|
67
67
|
def freeze
|
68
68
|
RSpec.warn_with("WARNING: you attempted to freeze a test double. This is explicitly a no-op as freezing doubles can lead to undesired behaviour when resetting tests.")
|
69
|
+
self
|
69
70
|
end
|
70
71
|
|
71
72
|
private
|
@@ -120,6 +120,11 @@ module RSpec
|
|
120
120
|
optional_callback_invocation_strategy.call(@doubled_module)
|
121
121
|
end
|
122
122
|
|
123
|
+
def ensure_implemented(_method_name)
|
124
|
+
return if Mocks.configuration.temporarily_suppress_partial_double_verification
|
125
|
+
super
|
126
|
+
end
|
127
|
+
|
123
128
|
def method_reference
|
124
129
|
@method_doubles
|
125
130
|
end
|
@@ -193,6 +198,8 @@ module RSpec
|
|
193
198
|
def self.for(object, method_name, proxy)
|
194
199
|
if ClassNewMethodReference.applies_to?(method_name) { object }
|
195
200
|
VerifyingExistingClassNewMethodDouble
|
201
|
+
elsif Mocks.configuration.temporarily_suppress_partial_double_verification
|
202
|
+
MethodDouble
|
196
203
|
else
|
197
204
|
self
|
198
205
|
end.new(object, method_name, proxy)
|
data/lib/rspec/mocks/version.rb
CHANGED
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.9.0
|
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: 2019-10-07 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.9.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.9.0
|
64
64
|
- !ruby/object:Gem::Dependency
|
65
65
|
name: diff-lcs
|
66
66
|
requirement: !ruby/object:Gem::Requirement
|
@@ -115,14 +115,14 @@ dependencies:
|
|
115
115
|
requirements:
|
116
116
|
- - "~>"
|
117
117
|
- !ruby/object:Gem::Version
|
118
|
-
version: 0.
|
118
|
+
version: 0.14.10
|
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.
|
125
|
+
version: 0.14.10
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: minitest
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -192,7 +192,12 @@ files:
|
|
192
192
|
homepage: https://github.com/rspec/rspec-mocks
|
193
193
|
licenses:
|
194
194
|
- MIT
|
195
|
-
metadata:
|
195
|
+
metadata:
|
196
|
+
bug_tracker_uri: https://github.com/rspec/rspec-mocks/issues
|
197
|
+
changelog_uri: https://github.com/rspec/rspec-mocks/blob/v3.9.0/Changelog.md
|
198
|
+
documentation_uri: https://rspec.info/documentation/
|
199
|
+
mailing_list_uri: https://groups.google.com/forum/#!forum/rspec
|
200
|
+
source_code_uri: https://github.com/rspec/rspec-mocks
|
196
201
|
post_install_message:
|
197
202
|
rdoc_options:
|
198
203
|
- "--charset=UTF-8"
|
@@ -209,10 +214,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
209
214
|
- !ruby/object:Gem::Version
|
210
215
|
version: '0'
|
211
216
|
requirements: []
|
212
|
-
|
213
|
-
rubygems_version: 2.5.1
|
217
|
+
rubygems_version: 3.0.6
|
214
218
|
signing_key:
|
215
219
|
specification_version: 4
|
216
|
-
summary: rspec-mocks-3.
|
220
|
+
summary: rspec-mocks-3.9.0
|
217
221
|
test_files: []
|
218
|
-
has_rdoc:
|
metadata.gz.sig
CHANGED
Binary file
|