rspec-mocks 3.0.0.beta1 → 3.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +1 -1
- data/Changelog.md +95 -3
- data/README.md +27 -13
- data/features/README.md +15 -7
- data/features/argument_matchers/README.md +5 -5
- data/features/argument_matchers/explicit.feature +6 -6
- data/features/argument_matchers/general_matchers.feature +4 -4
- data/features/argument_matchers/type_matchers.feature +2 -2
- data/features/message_expectations/README.md +29 -27
- data/features/message_expectations/call_original.feature +0 -1
- data/features/message_expectations/message_chains_using_expect.feature +49 -0
- data/features/method_stubs/README.md +2 -1
- data/features/method_stubs/{any_instance.feature → allow_any_instance_of.feature} +12 -12
- data/features/method_stubs/{stub_chain.feature → receive_message_chain.feature} +3 -3
- data/features/method_stubs/to_ary.feature +1 -1
- data/features/mutating_constants/stub_defined_constant.feature +0 -1
- data/features/outside_rspec/standalone.feature +1 -1
- data/features/spies/spy_pure_mock_method.feature +1 -1
- data/features/test_frameworks/test_unit.feature +21 -10
- data/features/verifying_doubles/README.md +17 -0
- data/features/verifying_doubles/class_doubles.feature +1 -16
- data/features/verifying_doubles/dynamic_classes.feature +0 -1
- data/features/verifying_doubles/{introduction.feature → instance_doubles.feature} +41 -23
- data/features/verifying_doubles/partial_doubles.feature +2 -2
- data/lib/rspec/mocks.rb +69 -82
- data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +35 -0
- data/lib/rspec/mocks/any_instance/expectation_chain.rb +1 -2
- data/lib/rspec/mocks/any_instance/recorder.rb +52 -18
- data/lib/rspec/mocks/any_instance/stub_chain.rb +1 -1
- data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +4 -0
- data/lib/rspec/mocks/argument_list_matcher.rb +10 -44
- data/lib/rspec/mocks/argument_matchers.rb +132 -163
- data/lib/rspec/mocks/configuration.rb +28 -4
- data/lib/rspec/mocks/error_generator.rb +46 -13
- data/lib/rspec/mocks/example_methods.rb +13 -12
- data/lib/rspec/mocks/extensions/marshal.rb +1 -1
- data/lib/rspec/mocks/framework.rb +3 -4
- data/lib/rspec/mocks/instance_method_stasher.rb +2 -3
- data/lib/rspec/mocks/matchers/have_received.rb +8 -6
- data/lib/rspec/mocks/matchers/receive.rb +28 -20
- data/lib/rspec/mocks/matchers/receive_message_chain.rb +65 -0
- data/lib/rspec/mocks/matchers/receive_messages.rb +3 -2
- data/lib/rspec/mocks/message_chain.rb +91 -0
- data/lib/rspec/mocks/message_expectation.rb +86 -80
- data/lib/rspec/mocks/method_double.rb +2 -11
- data/lib/rspec/mocks/method_reference.rb +82 -23
- data/lib/rspec/mocks/method_signature_verifier.rb +207 -0
- data/lib/rspec/mocks/mutate_const.rb +34 -50
- data/lib/rspec/mocks/object_reference.rb +0 -1
- data/lib/rspec/mocks/proxy.rb +70 -13
- data/lib/rspec/mocks/ruby_features.rb +24 -0
- data/lib/rspec/mocks/space.rb +105 -31
- data/lib/rspec/mocks/standalone.rb +2 -2
- data/lib/rspec/mocks/syntax.rb +43 -8
- data/lib/rspec/mocks/targets.rb +16 -7
- data/lib/rspec/mocks/test_double.rb +41 -15
- data/lib/rspec/mocks/verifying_double.rb +51 -4
- data/lib/rspec/mocks/verifying_message_expecation.rb +12 -12
- data/lib/rspec/mocks/verifying_proxy.rb +32 -19
- data/lib/rspec/mocks/version.rb +1 -1
- data/spec/rspec/mocks/and_call_original_spec.rb +28 -7
- data/spec/rspec/mocks/and_return_spec.rb +23 -0
- data/spec/rspec/mocks/and_yield_spec.rb +1 -2
- data/spec/rspec/mocks/any_instance_spec.rb +33 -17
- data/spec/rspec/mocks/array_including_matcher_spec.rb +6 -6
- data/spec/rspec/mocks/before_all_spec.rb +132 -0
- data/spec/rspec/mocks/block_return_value_spec.rb +12 -1
- data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +9 -11
- data/spec/rspec/mocks/configuration_spec.rb +14 -1
- data/spec/rspec/mocks/double_spec.rb +867 -24
- data/spec/rspec/mocks/example_methods_spec.rb +13 -0
- data/spec/rspec/mocks/extensions/marshal_spec.rb +17 -17
- data/spec/rspec/mocks/failing_argument_matchers_spec.rb +29 -1
- data/spec/rspec/mocks/hash_excluding_matcher_spec.rb +12 -12
- data/spec/rspec/mocks/hash_including_matcher_spec.rb +21 -17
- data/spec/rspec/mocks/instance_method_stasher_spec.rb +2 -3
- data/spec/rspec/mocks/matchers/have_received_spec.rb +7 -0
- data/spec/rspec/mocks/matchers/receive_message_chain_spec.rb +198 -0
- data/spec/rspec/mocks/matchers/receive_messages_spec.rb +2 -2
- data/spec/rspec/mocks/matchers/receive_spec.rb +19 -6
- data/spec/rspec/mocks/method_signature_verifier_spec.rb +272 -0
- data/spec/rspec/mocks/methods_spec.rb +0 -1
- data/spec/rspec/mocks/multiple_return_value_spec.rb +2 -2
- data/spec/rspec/mocks/mutate_const_spec.rb +24 -1
- data/spec/rspec/mocks/nil_expectation_warning_spec.rb +6 -22
- data/spec/rspec/mocks/null_object_mock_spec.rb +13 -7
- data/spec/rspec/mocks/options_hash_spec.rb +3 -3
- data/spec/rspec/mocks/{partial_mock_spec.rb → partial_double_spec.rb} +5 -2
- data/spec/rspec/mocks/{partial_mock_using_mocks_directly_spec.rb → partial_double_using_mocks_directly_spec.rb} +1 -1
- data/spec/rspec/mocks/passing_argument_matchers_spec.rb +18 -0
- data/spec/rspec/mocks/serialization_spec.rb +1 -0
- data/spec/rspec/mocks/space_spec.rb +218 -7
- data/spec/rspec/mocks/stub_chain_spec.rb +6 -0
- data/spec/rspec/mocks/stub_spec.rb +0 -6
- data/spec/rspec/mocks/syntax_spec.rb +19 -0
- data/spec/rspec/mocks/test_double_spec.rb +0 -1
- data/spec/rspec/mocks/verifying_double_spec.rb +281 -18
- data/spec/rspec/mocks/verifying_message_expecation_spec.rb +7 -6
- data/spec/rspec/mocks_spec.rb +168 -42
- data/spec/spec_helper.rb +34 -22
- metadata +94 -63
- metadata.gz.sig +0 -0
- checksums.yaml +0 -15
- checksums.yaml.gz.sig +0 -2
- data/features/outside_rspec/configuration.feature +0 -60
- data/lib/rspec/mocks/arity_calculator.rb +0 -66
- data/lib/rspec/mocks/errors.rb +0 -12
- data/lib/rspec/mocks/mock.rb +0 -7
- data/lib/rspec/mocks/proxy_for_nil.rb +0 -37
- data/lib/rspec/mocks/stub_chain.rb +0 -51
- data/spec/rspec/mocks/argument_expectation_spec.rb +0 -32
- data/spec/rspec/mocks/arity_calculator_spec.rb +0 -95
- data/spec/rspec/mocks/mock_space_spec.rb +0 -113
- data/spec/rspec/mocks/mock_spec.rb +0 -788
@@ -39,20 +39,44 @@ module RSpec
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
|
43
|
-
|
42
|
+
# Provides the ability to set either `expect`,
|
43
|
+
# `should` or both syntaxes. RSpec uses `expect`
|
44
|
+
# syntax by default. This is needed if you want to
|
45
|
+
# explicitly enable `should` syntax and/or explicitly
|
46
|
+
# disable `expect` syntax.
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
#
|
50
|
+
# RSpec.configure do |rspec|
|
51
|
+
# rspec.mock_with :rspec do |mocks|
|
52
|
+
# mocks.syntax = [:expect, :should]
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
def syntax=(*values)
|
57
|
+
syntaxes = values.flatten
|
58
|
+
if syntaxes.include?(:expect)
|
44
59
|
Syntax.enable_expect
|
45
60
|
else
|
46
61
|
Syntax.disable_expect
|
47
62
|
end
|
48
63
|
|
49
|
-
if
|
64
|
+
if syntaxes.include?(:should)
|
50
65
|
Syntax.enable_should
|
51
66
|
else
|
52
67
|
Syntax.disable_should
|
53
68
|
end
|
54
69
|
end
|
55
70
|
|
71
|
+
# Returns an array with a list of syntaxes
|
72
|
+
# that are enabled.
|
73
|
+
#
|
74
|
+
# @example
|
75
|
+
#
|
76
|
+
# unless RSpec::Mocks.configuration.syntax.include?(:expect)
|
77
|
+
# raise "this RSpec extension gem requires the rspec-mocks `:expect` syntax"
|
78
|
+
# end
|
79
|
+
#
|
56
80
|
def syntax
|
57
81
|
syntaxes = []
|
58
82
|
syntaxes << :should if Syntax.should_enabled?
|
@@ -84,7 +108,7 @@ module RSpec
|
|
84
108
|
end
|
85
109
|
|
86
110
|
# When set to true, partial mocks will be verified the same as object
|
87
|
-
# doubles. Any stubs will have their
|
111
|
+
# doubles. Any stubs will have their arguments checked against the original
|
88
112
|
# method, and methods that do not exist cannot be stubbed.
|
89
113
|
def verify_partial_doubles=(val)
|
90
114
|
@verify_partial_doubles = !!val
|
@@ -1,5 +1,25 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Mocks
|
3
|
+
# @public
|
4
|
+
# Raised when a message expectation is not satisfied.
|
5
|
+
MockExpectationError = Class.new(Exception)
|
6
|
+
|
7
|
+
# @public
|
8
|
+
# Raised when a test double is used after it has been torn
|
9
|
+
# down (typically at the end of an rspec-core example).
|
10
|
+
ExpiredTestDoubleError = Class.new(MockExpectationError)
|
11
|
+
|
12
|
+
# @public
|
13
|
+
# Raised when doubles or partial doubles are used outside of the per-test lifecycle.
|
14
|
+
OutsideOfExampleError = Class.new(StandardError)
|
15
|
+
|
16
|
+
# @private
|
17
|
+
UnsupportedMatcherError = Class.new(StandardError)
|
18
|
+
# @private
|
19
|
+
NegationUnsupportedError = Class.new(StandardError)
|
20
|
+
|
21
|
+
VerifyingDoubleNotDefinedError = Class.new(StandardError)
|
22
|
+
|
3
23
|
# @private
|
4
24
|
class ErrorGenerator
|
5
25
|
attr_writer :opts
|
@@ -56,13 +76,26 @@ module RSpec
|
|
56
76
|
end
|
57
77
|
|
58
78
|
# @private
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
actual
|
79
|
+
def raise_non_public_error(method_name, visibility)
|
80
|
+
raise NoMethodError, "%s method `%s' called on %s" % [
|
81
|
+
visibility, method_name, intro
|
63
82
|
]
|
64
83
|
end
|
65
84
|
|
85
|
+
# @private
|
86
|
+
def raise_invalid_arguments_error(verifier)
|
87
|
+
__raise verifier.error_message
|
88
|
+
end
|
89
|
+
|
90
|
+
# @private
|
91
|
+
def raise_expired_test_double_error
|
92
|
+
raise ExpiredTestDoubleError,
|
93
|
+
"#{intro} was originally created in one example but has leaked into " +
|
94
|
+
"another example and can no longer be used. rspec-mocks' doubles are " +
|
95
|
+
"designed to only last for one example, and you need to create a new " +
|
96
|
+
"one in each example you wish to use it for."
|
97
|
+
end
|
98
|
+
|
66
99
|
# @private
|
67
100
|
def received_part_of_expectation_error(actual_received_count, *args)
|
68
101
|
"received: #{count_message(actual_received_count)}" +
|
@@ -112,14 +145,14 @@ module RSpec
|
|
112
145
|
end
|
113
146
|
|
114
147
|
# @private
|
115
|
-
def raise_wrong_arity_error(args_to_yield,
|
116
|
-
__raise "#{intro} yielded |#{arg_list(*args_to_yield)}| to block with
|
148
|
+
def raise_wrong_arity_error(args_to_yield, signature)
|
149
|
+
__raise "#{intro} yielded |#{arg_list(*args_to_yield)}| to block with #{signature.description}"
|
117
150
|
end
|
118
151
|
|
119
152
|
# @private
|
120
|
-
def
|
121
|
-
__raise "#{intro} is a pure
|
122
|
-
"available on a partial
|
153
|
+
def raise_only_valid_on_a_partial_double(method)
|
154
|
+
__raise "#{intro} is a pure test double. `#{method}` is only " +
|
155
|
+
"available on a partial double."
|
123
156
|
end
|
124
157
|
|
125
158
|
# @private
|
@@ -189,12 +222,12 @@ module RSpec
|
|
189
222
|
end
|
190
223
|
|
191
224
|
def count_message(count, expectation_count_type=nil)
|
192
|
-
return "at least #{
|
193
|
-
return "at most #{
|
194
|
-
return
|
225
|
+
return "at least #{times(count.abs)}" if count < 0 || expectation_count_type == :at_least
|
226
|
+
return "at most #{times(count)}" if expectation_count_type == :at_most
|
227
|
+
return times(count)
|
195
228
|
end
|
196
229
|
|
197
|
-
def
|
230
|
+
def times(count)
|
198
231
|
"#{count} time#{count == 1 ? '' : 's'}"
|
199
232
|
end
|
200
233
|
|
@@ -12,9 +12,9 @@ module RSpec
|
|
12
12
|
# @param name [String/Symbol] (optional) used in
|
13
13
|
# clarify intent
|
14
14
|
# @param stubs (Hash) (optional) hash of message/return-value pairs
|
15
|
-
# @return (
|
15
|
+
# @return (Double)
|
16
16
|
#
|
17
|
-
# Constructs an instance of [RSpec::Mocks::
|
17
|
+
# Constructs an instance of [RSpec::Mocks::Double](RSpec::Mocks::Double) configured
|
18
18
|
# with an optional name, used for reporting in failure messages, and an optional
|
19
19
|
# hash of message/return-value pairs.
|
20
20
|
#
|
@@ -28,7 +28,7 @@ module RSpec
|
|
28
28
|
# card.rank #=> "A"
|
29
29
|
#
|
30
30
|
def double(*args)
|
31
|
-
declare_double(
|
31
|
+
ExampleMethods.declare_double(Double, *args)
|
32
32
|
end
|
33
33
|
|
34
34
|
# @overload instance_double(doubled_class)
|
@@ -43,7 +43,7 @@ module RSpec
|
|
43
43
|
# [double](double).
|
44
44
|
def instance_double(doubled_class, *args)
|
45
45
|
ref = ObjectReference.for(doubled_class)
|
46
|
-
declare_verifying_double(InstanceVerifyingDouble, ref, *args)
|
46
|
+
ExampleMethods.declare_verifying_double(InstanceVerifyingDouble, ref, *args)
|
47
47
|
end
|
48
48
|
|
49
49
|
# @overload class_double(doubled_class)
|
@@ -58,7 +58,7 @@ module RSpec
|
|
58
58
|
# [double](double).
|
59
59
|
def class_double(doubled_class, *args)
|
60
60
|
ref = ObjectReference.for(doubled_class)
|
61
|
-
declare_verifying_double(ClassVerifyingDouble, ref, *args)
|
61
|
+
ExampleMethods.declare_verifying_double(ClassVerifyingDouble, ref, *args)
|
62
62
|
end
|
63
63
|
|
64
64
|
# @overload object_double(object_or_name)
|
@@ -73,7 +73,7 @@ module RSpec
|
|
73
73
|
# for verification. In all other ways it behaves like a [double](double).
|
74
74
|
def object_double(object_or_name, *args)
|
75
75
|
ref = ObjectReference.for(object_or_name, :allow_direct_object_refs)
|
76
|
-
declare_verifying_double(ObjectVerifyingDouble, ref, *args)
|
76
|
+
ExampleMethods.declare_verifying_double(ObjectVerifyingDouble, ref, *args)
|
77
77
|
end
|
78
78
|
|
79
79
|
# Disables warning messages about expectations being set on nil.
|
@@ -164,6 +164,7 @@ module RSpec
|
|
164
164
|
Matchers::HaveReceived.new(method_name, &block)
|
165
165
|
end
|
166
166
|
|
167
|
+
# @api private
|
167
168
|
def self.included(klass)
|
168
169
|
klass.class_exec do
|
169
170
|
# This gets mixed in so that if `RSpec::Matchers` is included in
|
@@ -172,14 +173,13 @@ module RSpec
|
|
172
173
|
end
|
173
174
|
end
|
174
175
|
|
175
|
-
|
176
|
-
|
177
|
-
def declare_verifying_double(type, ref, *args)
|
176
|
+
# @api private
|
177
|
+
def self.declare_verifying_double(type, ref, *args)
|
178
178
|
if RSpec::Mocks.configuration.verify_doubled_constant_names? &&
|
179
179
|
!ref.defined?
|
180
180
|
|
181
|
-
raise
|
182
|
-
"#{ref.
|
181
|
+
raise VerifyingDoubleNotDefinedError,
|
182
|
+
"#{ref.description} is not a defined constant. " +
|
183
183
|
"Perhaps you misspelt it? " +
|
184
184
|
"Disable check with verify_doubled_constant_names configuration option."
|
185
185
|
end
|
@@ -187,7 +187,8 @@ module RSpec
|
|
187
187
|
declare_double(type, ref, *args)
|
188
188
|
end
|
189
189
|
|
190
|
-
|
190
|
+
# @api private
|
191
|
+
def self.declare_double(type, *args)
|
191
192
|
args << {} unless Hash === args.last
|
192
193
|
type.new(*args)
|
193
194
|
end
|
@@ -3,7 +3,7 @@ module Marshal
|
|
3
3
|
# Duplicates any mock objects before serialization. Otherwise,
|
4
4
|
# serialization will fail because methods exist on the singleton class.
|
5
5
|
def dump_with_mocks(object, *rest)
|
6
|
-
if
|
6
|
+
if !::RSpec::Mocks.space.registered?(object) || NilClass === object
|
7
7
|
dump_without_mocks(object, *rest)
|
8
8
|
else
|
9
9
|
dump_without_mocks(object.dup, *rest)
|
@@ -9,19 +9,17 @@ require 'rspec/mocks/method_double'
|
|
9
9
|
require 'rspec/mocks/argument_matchers'
|
10
10
|
require 'rspec/mocks/example_methods'
|
11
11
|
require 'rspec/mocks/proxy'
|
12
|
-
require 'rspec/mocks/proxy_for_nil'
|
13
12
|
require 'rspec/mocks/test_double'
|
14
|
-
require 'rspec/mocks/mock'
|
15
13
|
require 'rspec/mocks/argument_list_matcher'
|
16
14
|
require 'rspec/mocks/message_expectation'
|
17
15
|
require 'rspec/mocks/order_group'
|
18
|
-
require 'rspec/mocks/errors'
|
19
16
|
require 'rspec/mocks/error_generator'
|
20
17
|
require 'rspec/mocks/space'
|
21
18
|
require 'rspec/mocks/extensions/marshal'
|
22
19
|
require 'rspec/mocks/any_instance/chain'
|
23
20
|
require 'rspec/mocks/any_instance/stub_chain'
|
24
21
|
require 'rspec/mocks/any_instance/stub_chain_chain'
|
22
|
+
require 'rspec/mocks/any_instance/expect_chain_chain'
|
25
23
|
require 'rspec/mocks/any_instance/expectation_chain'
|
26
24
|
require 'rspec/mocks/any_instance/message_chains'
|
27
25
|
require 'rspec/mocks/any_instance/recorder'
|
@@ -29,7 +27,8 @@ require 'rspec/mocks/mutate_const'
|
|
29
27
|
require 'rspec/mocks/matchers/have_received'
|
30
28
|
require 'rspec/mocks/matchers/receive'
|
31
29
|
require 'rspec/mocks/matchers/receive_messages'
|
32
|
-
require 'rspec/mocks/
|
30
|
+
require 'rspec/mocks/matchers/receive_message_chain'
|
31
|
+
require 'rspec/mocks/message_chain'
|
33
32
|
require 'rspec/mocks/targets'
|
34
33
|
require 'rspec/mocks/syntax'
|
35
34
|
require 'rspec/mocks/configuration'
|
@@ -54,7 +54,7 @@ module RSpec
|
|
54
54
|
# @private
|
55
55
|
def stash
|
56
56
|
return if !method_defined_directly_on_klass?
|
57
|
-
@original_method ||= ::RSpec::
|
57
|
+
@original_method ||= ::RSpec::Support.method_handle_for(@object, @method)
|
58
58
|
end
|
59
59
|
|
60
60
|
# @private
|
@@ -79,7 +79,7 @@ module RSpec
|
|
79
79
|
|
80
80
|
# @private
|
81
81
|
def method_defined_on_klass?(klass = @klass)
|
82
|
-
|
82
|
+
MethodReference.method_defined_at_any_visibility?(klass, @method)
|
83
83
|
end
|
84
84
|
|
85
85
|
def method_owned_by_klass?
|
@@ -109,4 +109,3 @@ module RSpec
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
end
|
112
|
-
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Mocks
|
3
3
|
module Matchers
|
4
|
+
# @private
|
4
5
|
class HaveReceived
|
5
6
|
COUNT_CONSTRAINTS = %w(exactly at_least at_most times once twice)
|
6
7
|
ARGS_CONSTRAINTS = %w(with)
|
@@ -35,7 +36,7 @@ module RSpec
|
|
35
36
|
generate_failure_message
|
36
37
|
end
|
37
38
|
|
38
|
-
def
|
39
|
+
def failure_message_when_negated
|
39
40
|
generate_failure_message
|
40
41
|
end
|
41
42
|
|
@@ -53,9 +54,11 @@ module RSpec
|
|
53
54
|
private
|
54
55
|
|
55
56
|
def expect
|
56
|
-
expectation
|
57
|
-
|
58
|
-
|
57
|
+
@expectation ||= begin
|
58
|
+
expectation = mock_proxy.build_expectation(@method_name)
|
59
|
+
apply_constraints_to expectation
|
60
|
+
expectation
|
61
|
+
end
|
59
62
|
end
|
60
63
|
|
61
64
|
def apply_constraints_to(expectation)
|
@@ -90,10 +93,9 @@ module RSpec
|
|
90
93
|
end
|
91
94
|
|
92
95
|
def mock_proxy
|
93
|
-
RSpec::Mocks.proxy_for(@subject)
|
96
|
+
RSpec::Mocks.space.proxy_for(@subject)
|
94
97
|
end
|
95
98
|
end
|
96
99
|
end
|
97
100
|
end
|
98
101
|
end
|
99
|
-
|
@@ -1,17 +1,13 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Mocks
|
3
3
|
module Matchers
|
4
|
+
# @private
|
4
5
|
class Receive
|
5
6
|
def initialize(message, block)
|
6
7
|
@message = message
|
7
8
|
@block = block
|
8
9
|
@recorded_customizations = []
|
9
|
-
|
10
|
-
# MRI, JRuby and RBX report the caller inconsistently; MRI
|
11
|
-
# reports an extra "in `new'" line in the backtrace that the
|
12
|
-
# others do not include. The safest way to find the right
|
13
|
-
# line is to search for the first line BEFORE rspec/mocks/syntax.rb.
|
14
|
-
@backtrace_line = CallerFilter.first_non_rspec_line
|
10
|
+
@backtrace_line = CallerFilter.first_non_rspec_line
|
15
11
|
end
|
16
12
|
|
17
13
|
def name
|
@@ -27,7 +23,7 @@ module RSpec
|
|
27
23
|
def setup_negative_expectation(subject, &block)
|
28
24
|
# ensure `never` goes first for cases like `never.and_return(5)`,
|
29
25
|
# where `and_return` is meant to raise an error
|
30
|
-
@recorded_customizations.unshift
|
26
|
+
@recorded_customizations.unshift ExpectationCustomization.new(:never, [], nil)
|
31
27
|
|
32
28
|
warn_if_any_instance("expect", subject)
|
33
29
|
|
@@ -56,7 +52,7 @@ module RSpec
|
|
56
52
|
next if method_defined?(method)
|
57
53
|
|
58
54
|
define_method(method) do |*args, &block|
|
59
|
-
@recorded_customizations <<
|
55
|
+
@recorded_customizations << ExpectationCustomization.new(method, args, block)
|
60
56
|
self
|
61
57
|
end
|
62
58
|
end
|
@@ -75,17 +71,19 @@ module RSpec
|
|
75
71
|
end
|
76
72
|
|
77
73
|
def setup_mock_proxy_method_substitute(subject, method, block)
|
78
|
-
proxy = ::RSpec::Mocks.proxy_for(subject)
|
74
|
+
proxy = ::RSpec::Mocks.space.proxy_for(subject)
|
79
75
|
setup_method_substitute(proxy, method, block, @backtrace_line)
|
80
76
|
end
|
81
77
|
|
82
78
|
def setup_any_instance_method_substitute(subject, method, block)
|
83
|
-
any_instance_recorder = ::RSpec::Mocks.any_instance_recorder_for(subject)
|
79
|
+
any_instance_recorder = ::RSpec::Mocks.space.any_instance_recorder_for(subject)
|
84
80
|
setup_method_substitute(any_instance_recorder, method, block)
|
85
81
|
end
|
86
82
|
|
87
83
|
def setup_method_substitute(host, method, block, *args)
|
88
84
|
args << @message.to_sym
|
85
|
+
block = move_block_to_last_customization(block)
|
86
|
+
|
89
87
|
expectation = host.__send__(method, *args, &(@block || block))
|
90
88
|
|
91
89
|
@recorded_customizations.each do |customization|
|
@@ -94,19 +92,29 @@ module RSpec
|
|
94
92
|
expectation
|
95
93
|
end
|
96
94
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
@args = args
|
101
|
-
@block = block
|
102
|
-
end
|
95
|
+
def move_block_to_last_customization(block)
|
96
|
+
last = @recorded_customizations.last
|
97
|
+
return block unless last
|
103
98
|
|
104
|
-
|
105
|
-
|
106
|
-
end
|
99
|
+
last.block ||= block
|
100
|
+
nil
|
107
101
|
end
|
108
102
|
end
|
109
103
|
end
|
104
|
+
|
105
|
+
# @private
|
106
|
+
class ExpectationCustomization
|
107
|
+
attr_accessor :block
|
108
|
+
|
109
|
+
def initialize(method_name, args, block)
|
110
|
+
@method_name = method_name
|
111
|
+
@args = args
|
112
|
+
@block = block
|
113
|
+
end
|
114
|
+
|
115
|
+
def playback_onto(expectation)
|
116
|
+
expectation.__send__(@method_name, *@args, &@block)
|
117
|
+
end
|
118
|
+
end
|
110
119
|
end
|
111
120
|
end
|
112
|
-
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Mocks
|
3
|
+
module Matchers
|
4
|
+
# @private
|
5
|
+
class ReceiveMessageChain
|
6
|
+
def initialize(chain, &block)
|
7
|
+
@chain = chain
|
8
|
+
@block = block
|
9
|
+
@recorded_customizations = []
|
10
|
+
end
|
11
|
+
|
12
|
+
[:and_return, :and_throw, :and_raise, :and_yield, :and_call_original].each do |msg|
|
13
|
+
define_method(msg) do |*args, &block|
|
14
|
+
@recorded_customizations << ExpectationCustomization.new(msg, args, block)
|
15
|
+
self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def name
|
20
|
+
"receive_message_chain"
|
21
|
+
end
|
22
|
+
|
23
|
+
def setup_allowance(subject, &block)
|
24
|
+
chain = StubChain.stub_chain_on(subject, *@chain, &(@block || block))
|
25
|
+
replay_customizations(chain)
|
26
|
+
end
|
27
|
+
|
28
|
+
def setup_any_instance_allowance(subject, &block)
|
29
|
+
recorder = ::RSpec::Mocks.space.any_instance_recorder_for(subject)
|
30
|
+
chain = recorder.stub_chain(*@chain, &(@block || block))
|
31
|
+
replay_customizations(chain)
|
32
|
+
end
|
33
|
+
|
34
|
+
def setup_any_instance_expectation(subject, &block)
|
35
|
+
recorder = ::RSpec::Mocks.space.any_instance_recorder_for(subject)
|
36
|
+
chain = recorder.expect_chain(*@chain, &(@block || block))
|
37
|
+
replay_customizations(chain)
|
38
|
+
end
|
39
|
+
|
40
|
+
def setup_expectation(subject, &block)
|
41
|
+
chain = ExpectChain.expect_chain_on(subject, *@chain, &(@block || block))
|
42
|
+
replay_customizations(chain)
|
43
|
+
end
|
44
|
+
|
45
|
+
def setup_negative_expectation(*args)
|
46
|
+
raise NegationUnsupportedError.new(
|
47
|
+
"`expect(...).not_to receive_message_chain` is not supported " +
|
48
|
+
"since it doesn't really make sense. What would it even mean?"
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
alias matches? setup_expectation
|
53
|
+
alias does_not_match? setup_negative_expectation
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def replay_customizations(chain)
|
58
|
+
@recorded_customizations.each do |customization|
|
59
|
+
customization.playback_onto(chain)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|