rspec-mocks 2.11.3 → 3.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/.document +1 -1
  4. data/.yardopts +1 -1
  5. data/Changelog.md +989 -21
  6. data/{License.txt → LICENSE.md} +5 -3
  7. data/README.md +260 -73
  8. data/lib/rspec/mocks/any_instance/chain.rb +58 -24
  9. data/lib/rspec/mocks/any_instance/error_generator.rb +31 -0
  10. data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +31 -0
  11. data/lib/rspec/mocks/any_instance/expectation_chain.rb +23 -30
  12. data/lib/rspec/mocks/any_instance/message_chains.rb +38 -15
  13. data/lib/rspec/mocks/any_instance/proxy.rb +116 -0
  14. data/lib/rspec/mocks/any_instance/recorder.rb +155 -59
  15. data/lib/rspec/mocks/any_instance/stub_chain.rb +33 -19
  16. data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +10 -12
  17. data/lib/rspec/mocks/any_instance.rb +11 -81
  18. data/lib/rspec/mocks/argument_list_matcher.rb +59 -37
  19. data/lib/rspec/mocks/argument_matchers.rb +233 -149
  20. data/lib/rspec/mocks/configuration.rb +212 -0
  21. data/lib/rspec/mocks/error_generator.rb +304 -49
  22. data/lib/rspec/mocks/example_methods.rb +361 -22
  23. data/lib/rspec/mocks/instance_method_stasher.rb +146 -0
  24. data/lib/rspec/mocks/marshal_extension.rb +41 -0
  25. data/lib/rspec/mocks/matchers/expectation_customization.rb +20 -0
  26. data/lib/rspec/mocks/matchers/have_received.rb +134 -0
  27. data/lib/rspec/mocks/matchers/receive.rb +133 -0
  28. data/lib/rspec/mocks/matchers/receive_message_chain.rb +82 -0
  29. data/lib/rspec/mocks/matchers/receive_messages.rb +77 -0
  30. data/lib/rspec/mocks/message_chain.rb +87 -0
  31. data/lib/rspec/mocks/message_expectation.rb +648 -314
  32. data/lib/rspec/mocks/method_double.rb +185 -58
  33. data/lib/rspec/mocks/method_reference.rb +202 -0
  34. data/lib/rspec/mocks/minitest_integration.rb +68 -0
  35. data/lib/rspec/mocks/mutate_const.rb +339 -0
  36. data/lib/rspec/mocks/object_reference.rb +149 -0
  37. data/lib/rspec/mocks/order_group.rb +48 -7
  38. data/lib/rspec/mocks/proxy.rb +405 -74
  39. data/lib/rspec/mocks/space.rb +219 -15
  40. data/lib/rspec/mocks/standalone.rb +2 -2
  41. data/lib/rspec/mocks/syntax.rb +325 -0
  42. data/lib/rspec/mocks/targets.rb +124 -0
  43. data/lib/rspec/mocks/test_double.rb +125 -57
  44. data/lib/rspec/mocks/verifying_double.rb +121 -0
  45. data/lib/rspec/mocks/verifying_message_expectation.rb +54 -0
  46. data/lib/rspec/mocks/verifying_proxy.rb +220 -0
  47. data/lib/rspec/mocks/version.rb +3 -1
  48. data/lib/rspec/mocks.rb +121 -27
  49. data.tar.gz.sig +0 -0
  50. metadata +178 -253
  51. metadata.gz.sig +3 -0
  52. data/features/README.md +0 -67
  53. data/features/Scope.md +0 -17
  54. data/features/Upgrade.md +0 -22
  55. data/features/argument_matchers/README.md +0 -27
  56. data/features/argument_matchers/explicit.feature +0 -60
  57. data/features/argument_matchers/general_matchers.feature +0 -85
  58. data/features/argument_matchers/type_matchers.feature +0 -27
  59. data/features/message_expectations/README.md +0 -69
  60. data/features/message_expectations/any_instance.feature +0 -21
  61. data/features/message_expectations/block_local_expectations.feature.pending +0 -55
  62. data/features/message_expectations/expect_message.feature +0 -94
  63. data/features/message_expectations/receive_counts.feature +0 -209
  64. data/features/message_expectations/warn_when_expectation_is_set_on_nil.feature +0 -50
  65. data/features/method_stubs/README.md +0 -47
  66. data/features/method_stubs/any_instance.feature +0 -133
  67. data/features/method_stubs/as_null_object.feature +0 -35
  68. data/features/method_stubs/simple_return_value.feature +0 -64
  69. data/features/method_stubs/stub_chain.feature +0 -51
  70. data/features/method_stubs/stub_implementation.feature +0 -26
  71. data/features/method_stubs/to_ary.feature +0 -47
  72. data/features/outside_rspec/configuration.feature +0 -82
  73. data/features/outside_rspec/standalone.feature +0 -32
  74. data/features/step_definitions/additional_cli_steps.rb +0 -4
  75. data/features/stubbing_constants/README.md +0 -62
  76. data/features/stubbing_constants/stub_defined_constant.feature +0 -79
  77. data/features/stubbing_constants/stub_undefined_constant.feature +0 -50
  78. data/features/support/env.rb +0 -6
  79. data/lib/rspec/mocks/errors.rb +0 -12
  80. data/lib/rspec/mocks/extensions/instance_exec.rb +0 -34
  81. data/lib/rspec/mocks/extensions/marshal.rb +0 -23
  82. data/lib/rspec/mocks/extensions/psych.rb +0 -23
  83. data/lib/rspec/mocks/framework.rb +0 -21
  84. data/lib/rspec/mocks/methods.rb +0 -155
  85. data/lib/rspec/mocks/mock.rb +0 -7
  86. data/lib/rspec/mocks/serialization.rb +0 -34
  87. data/lib/rspec/mocks/stashed_instance_method.rb +0 -60
  88. data/lib/rspec/mocks/stub_const.rb +0 -332
  89. data/lib/spec/mocks.rb +0 -2
  90. data/spec/rspec/mocks/and_yield_spec.rb +0 -114
  91. data/spec/rspec/mocks/any_instance/message_chains_spec.rb +0 -40
  92. data/spec/rspec/mocks/any_instance_spec.rb +0 -877
  93. data/spec/rspec/mocks/any_number_of_times_spec.rb +0 -30
  94. data/spec/rspec/mocks/argument_expectation_spec.rb +0 -34
  95. data/spec/rspec/mocks/at_least_spec.rb +0 -142
  96. data/spec/rspec/mocks/at_most_spec.rb +0 -90
  97. data/spec/rspec/mocks/block_return_value_spec.rb +0 -53
  98. data/spec/rspec/mocks/bug_report_10260_spec.rb +0 -8
  99. data/spec/rspec/mocks/bug_report_10263_spec.rb +0 -25
  100. data/spec/rspec/mocks/bug_report_11545_spec.rb +0 -32
  101. data/spec/rspec/mocks/bug_report_496_spec.rb +0 -17
  102. data/spec/rspec/mocks/bug_report_600_spec.rb +0 -22
  103. data/spec/rspec/mocks/bug_report_7611_spec.rb +0 -16
  104. data/spec/rspec/mocks/bug_report_8165_spec.rb +0 -31
  105. data/spec/rspec/mocks/bug_report_830_spec.rb +0 -21
  106. data/spec/rspec/mocks/bug_report_957_spec.rb +0 -22
  107. data/spec/rspec/mocks/double_spec.rb +0 -12
  108. data/spec/rspec/mocks/failing_argument_matchers_spec.rb +0 -95
  109. data/spec/rspec/mocks/hash_excluding_matcher_spec.rb +0 -67
  110. data/spec/rspec/mocks/hash_including_matcher_spec.rb +0 -90
  111. data/spec/rspec/mocks/mock_ordering_spec.rb +0 -103
  112. data/spec/rspec/mocks/mock_space_spec.rb +0 -58
  113. data/spec/rspec/mocks/mock_spec.rb +0 -730
  114. data/spec/rspec/mocks/multiple_return_value_spec.rb +0 -119
  115. data/spec/rspec/mocks/nil_expectation_warning_spec.rb +0 -62
  116. data/spec/rspec/mocks/null_object_mock_spec.rb +0 -106
  117. data/spec/rspec/mocks/once_counts_spec.rb +0 -52
  118. data/spec/rspec/mocks/options_hash_spec.rb +0 -35
  119. data/spec/rspec/mocks/partial_mock_spec.rb +0 -171
  120. data/spec/rspec/mocks/partial_mock_using_mocks_directly_spec.rb +0 -95
  121. data/spec/rspec/mocks/passing_argument_matchers_spec.rb +0 -142
  122. data/spec/rspec/mocks/precise_counts_spec.rb +0 -68
  123. data/spec/rspec/mocks/record_messages_spec.rb +0 -26
  124. data/spec/rspec/mocks/serialization_spec.rb +0 -111
  125. data/spec/rspec/mocks/stash_spec.rb +0 -27
  126. data/spec/rspec/mocks/stashed_instance_method_spec.rb +0 -53
  127. data/spec/rspec/mocks/stub_chain_spec.rb +0 -154
  128. data/spec/rspec/mocks/stub_const_spec.rb +0 -334
  129. data/spec/rspec/mocks/stub_implementation_spec.rb +0 -81
  130. data/spec/rspec/mocks/stub_spec.rb +0 -247
  131. data/spec/rspec/mocks/stubbed_message_expectations_spec.rb +0 -47
  132. data/spec/rspec/mocks/test_double_spec.rb +0 -57
  133. data/spec/rspec/mocks/to_ary_spec.rb +0 -40
  134. data/spec/rspec/mocks/twice_counts_spec.rb +0 -66
  135. data/spec/rspec/mocks_spec.rb +0 -51
  136. data/spec/spec_helper.rb +0 -21
@@ -1,6 +1,10 @@
1
+ # This cannot take advantage of our relative requires, since this file is a
2
+ # dependency of `rspec/mocks/argument_list_matcher.rb`. See comment there for
3
+ # details.
4
+ require 'rspec/support/matcher_definition'
5
+
1
6
  module RSpec
2
7
  module Mocks
3
-
4
8
  # ArgumentMatchers are placeholders that you can include in message
5
9
  # expectations to match arguments against a broader check than simple
6
10
  # equality.
@@ -10,228 +14,308 @@ module RSpec
10
14
  #
11
15
  # @see ArgumentListMatcher
12
16
  module ArgumentMatchers
17
+ # Acts like an arg splat, matching any number of args at any point in an arg list.
18
+ #
19
+ # @example
20
+ # expect(object).to receive(:message).with(1, 2, any_args)
21
+ #
22
+ # # matches any of these:
23
+ # object.message(1, 2)
24
+ # object.message(1, 2, 3)
25
+ # object.message(1, 2, 3, 4)
26
+ def any_args
27
+ AnyArgsMatcher::INSTANCE
28
+ end
13
29
 
14
- class AnyArgsMatcher
15
- def description
16
- "any args"
17
- end
30
+ # Matches any argument at all.
31
+ #
32
+ # @example
33
+ # expect(object).to receive(:message).with(anything)
34
+ def anything
35
+ AnyArgMatcher::INSTANCE
18
36
  end
19
37
 
20
- class AnyArgMatcher
21
- def initialize(ignore)
22
- end
38
+ # Matches no arguments.
39
+ #
40
+ # @example
41
+ # expect(object).to receive(:message).with(no_args)
42
+ def no_args
43
+ NoArgsMatcher::INSTANCE
44
+ end
23
45
 
24
- def ==(other)
25
- true
46
+ # Matches if the actual argument responds to the specified messages.
47
+ #
48
+ # @example
49
+ # expect(object).to receive(:message).with(duck_type(:hello))
50
+ # expect(object).to receive(:message).with(duck_type(:hello, :goodbye))
51
+ def duck_type(*args)
52
+ DuckTypeMatcher.new(*args)
53
+ end
54
+
55
+ # Matches a boolean value.
56
+ #
57
+ # @example
58
+ # expect(object).to receive(:message).with(boolean())
59
+ def boolean
60
+ BooleanMatcher::INSTANCE
61
+ end
62
+
63
+ # Matches a hash that includes the specified key(s) or key/value pairs.
64
+ # Ignores any additional keys.
65
+ #
66
+ # @example
67
+ # expect(object).to receive(:message).with(hash_including(:key => val))
68
+ # expect(object).to receive(:message).with(hash_including(:key))
69
+ # expect(object).to receive(:message).with(hash_including(:key, :key2 => val2))
70
+ def hash_including(*args)
71
+ HashIncludingMatcher.new(ArgumentMatchers.anythingize_lonely_keys(*args))
72
+ end
73
+
74
+ # Matches an array that includes the specified items at least once.
75
+ # Ignores duplicates and additional values
76
+ #
77
+ # @example
78
+ # expect(object).to receive(:message).with(array_including(1,2,3))
79
+ # expect(object).to receive(:message).with(array_including([1,2,3]))
80
+ def array_including(*args)
81
+ actually_an_array = Array === args.first && args.count == 1 ? args.first : args
82
+ ArrayIncludingMatcher.new(actually_an_array)
83
+ end
84
+
85
+ # Matches a hash that doesn't include the specified key(s) or key/value.
86
+ #
87
+ # @example
88
+ # expect(object).to receive(:message).with(hash_excluding(:key => val))
89
+ # expect(object).to receive(:message).with(hash_excluding(:key))
90
+ # expect(object).to receive(:message).with(hash_excluding(:key, :key2 => :val2))
91
+ def hash_excluding(*args)
92
+ HashExcludingMatcher.new(ArgumentMatchers.anythingize_lonely_keys(*args))
93
+ end
94
+
95
+ alias_method :hash_not_including, :hash_excluding
96
+
97
+ # Matches if `arg.instance_of?(klass)`
98
+ #
99
+ # @example
100
+ # expect(object).to receive(:message).with(instance_of(Thing))
101
+ def instance_of(klass)
102
+ InstanceOf.new(klass)
103
+ end
104
+
105
+ alias_method :an_instance_of, :instance_of
106
+
107
+ # Matches if `arg.kind_of?(klass)`
108
+ #
109
+ # @example
110
+ # expect(object).to receive(:message).with(kind_of(Thing))
111
+ def kind_of(klass)
112
+ KindOf.new(klass)
113
+ end
114
+
115
+ alias_method :a_kind_of, :kind_of
116
+
117
+ # @private
118
+ def self.anythingize_lonely_keys(*args)
119
+ hash = Hash === args.last ? args.delete_at(-1) : {}
120
+ args.each { | arg | hash[arg] = AnyArgMatcher::INSTANCE }
121
+ hash
122
+ end
123
+
124
+ # Intended to be subclassed by stateless, immutable argument matchers.
125
+ # Provides a `<klass name>::INSTANCE` constant for accessing a global
126
+ # singleton instance of the matcher. There is no need to construct
127
+ # multiple instance since there is no state. It also facilities the
128
+ # special case logic we need for some of these matchers, by making it
129
+ # easy to do comparisons like: `[klass::INSTANCE] == args` rather than
130
+ # `args.count == 1 && klass === args.first`.
131
+ #
132
+ # @private
133
+ class SingletonMatcher
134
+ private_class_method :new
135
+
136
+ def self.inherited(subklass)
137
+ subklass.const_set(:INSTANCE, subklass.send(:new))
26
138
  end
27
139
  end
28
140
 
29
- class NoArgsMatcher
141
+ # @private
142
+ class AnyArgsMatcher < SingletonMatcher
30
143
  def description
31
- "no args"
144
+ "*(any args)"
32
145
  end
33
146
  end
34
147
 
35
- class RegexpMatcher
36
- def initialize(regexp)
37
- @regexp = regexp
148
+ # @private
149
+ class AnyArgMatcher < SingletonMatcher
150
+ def ===(_other)
151
+ true
152
+ end
153
+
154
+ def description
155
+ "anything"
38
156
  end
157
+ end
39
158
 
40
- def ==(value)
41
- Regexp === value ? value == @regexp : value =~ @regexp
159
+ # @private
160
+ class NoArgsMatcher < SingletonMatcher
161
+ def description
162
+ "no args"
42
163
  end
43
164
  end
44
165
 
45
- class BooleanMatcher
46
- def initialize(ignore)
166
+ # @private
167
+ class BooleanMatcher < SingletonMatcher
168
+ def ===(value)
169
+ true == value || false == value
47
170
  end
48
171
 
49
- def ==(value)
50
- [true,false].include?(value)
172
+ def description
173
+ "boolean"
51
174
  end
52
175
  end
53
176
 
54
- class HashIncludingMatcher
177
+ # @private
178
+ class BaseHashMatcher
55
179
  def initialize(expected)
56
180
  @expected = expected
57
181
  end
58
182
 
59
- def ==(actual)
60
- @expected.all? {|k,v| actual.has_key?(k) && v == actual[k]}
183
+ def ===(predicate, actual)
184
+ @expected.__send__(predicate) do |k, v|
185
+ actual.key?(k) && Support::FuzzyMatcher.values_match?(v, actual[k])
186
+ end
61
187
  rescue NoMethodError
62
188
  false
63
189
  end
64
190
 
191
+ def description(name)
192
+ "#{name}(#{formatted_expected_hash.inspect.sub(/^\{/, "").sub(/\}$/, "")})"
193
+ end
194
+
195
+ private
196
+
197
+ def formatted_expected_hash
198
+ Hash[
199
+ @expected.map do |k, v|
200
+ k = RSpec::Support.rspec_description_for_object(k)
201
+ v = RSpec::Support.rspec_description_for_object(v)
202
+
203
+ [k, v]
204
+ end
205
+ ]
206
+ end
207
+ end
208
+
209
+ # @private
210
+ class HashIncludingMatcher < BaseHashMatcher
211
+ def ===(actual)
212
+ super(:all?, actual)
213
+ end
214
+
215
+ def description
216
+ super("hash_including")
217
+ end
218
+ end
219
+
220
+ # @private
221
+ class HashExcludingMatcher < BaseHashMatcher
222
+ def ===(actual)
223
+ super(:none?, actual)
224
+ end
225
+
65
226
  def description
66
- "hash_including(#{@expected.inspect.sub(/^\{/,"").sub(/\}$/,"")})"
227
+ super("hash_not_including")
67
228
  end
68
229
  end
69
230
 
70
- class HashExcludingMatcher
231
+ # @private
232
+ class ArrayIncludingMatcher
71
233
  def initialize(expected)
72
234
  @expected = expected
73
235
  end
74
236
 
75
- def ==(actual)
76
- @expected.none? {|k,v| actual.has_key?(k) && v == actual[k]}
237
+ def ===(actual)
238
+ actual = actual.uniq
239
+ @expected.uniq.all? do |expected_element|
240
+ actual.any? do |actual_element|
241
+ RSpec::Support::FuzzyMatcher.values_match?(expected_element, actual_element)
242
+ end
243
+ end
77
244
  rescue NoMethodError
78
245
  false
79
246
  end
80
247
 
81
248
  def description
82
- "hash_not_including(#{@expected.inspect.sub(/^\{/,"").sub(/\}$/,"")})"
249
+ "array_including(#{formatted_expected_values})"
83
250
  end
84
- end
85
251
 
86
- class DuckTypeMatcher
87
- def initialize(*methods_to_respond_to)
88
- @methods_to_respond_to = methods_to_respond_to
89
- end
252
+ private
90
253
 
91
- def ==(value)
92
- @methods_to_respond_to.all? {|message| value.respond_to?(message)}
254
+ def formatted_expected_values
255
+ @expected.map do |x|
256
+ RSpec::Support.rspec_description_for_object(x)
257
+ end.join(", ")
93
258
  end
94
259
  end
95
260
 
96
- class MatcherMatcher
97
- def initialize(matcher)
98
- @matcher = matcher
99
- end
100
-
101
- def ==(value)
102
- @matcher.matches?(value)
261
+ # @private
262
+ class DuckTypeMatcher
263
+ def initialize(*methods_to_respond_to)
264
+ @methods_to_respond_to = methods_to_respond_to
103
265
  end
104
- end
105
266
 
106
- class EqualityProxy
107
- def initialize(given)
108
- @given = given
267
+ def ===(value)
268
+ @methods_to_respond_to.all? { |message| value.respond_to?(message) }
109
269
  end
110
270
 
111
- def ==(expected)
112
- @given == expected
271
+ def description
272
+ "duck_type(#{@methods_to_respond_to.map(&:inspect).join(', ')})"
113
273
  end
114
274
  end
115
275
 
276
+ # @private
116
277
  class InstanceOf
117
278
  def initialize(klass)
118
279
  @klass = klass
119
280
  end
120
281
 
121
- def ==(actual)
282
+ def ===(actual)
122
283
  actual.instance_of?(@klass)
123
284
  end
285
+
286
+ def description
287
+ "an_instance_of(#{@klass.name})"
288
+ end
124
289
  end
125
290
 
291
+ # @private
126
292
  class KindOf
127
293
  def initialize(klass)
128
294
  @klass = klass
129
295
  end
130
296
 
131
- def ==(actual)
297
+ def ===(actual)
132
298
  actual.kind_of?(@klass)
133
299
  end
134
- end
135
300
 
136
- # Matches any args at all. Supports a more explicit variation of
137
- # `object.should_receive(:message)`
138
- #
139
- # @example
140
- #
141
- # object.should_receive(:message).with(any_args)
142
- def any_args
143
- AnyArgsMatcher.new
144
- end
145
-
146
- # Matches any argument at all.
147
- #
148
- # @example
149
- #
150
- # object.should_receive(:message).with(anything)
151
- def anything
152
- AnyArgMatcher.new(nil)
153
- end
154
-
155
- # Matches no arguments.
156
- #
157
- # @example
158
- #
159
- # object.should_receive(:message).with(no_args)
160
- def no_args
161
- NoArgsMatcher.new
162
- end
163
-
164
- # Matches if the actual argument responds to the specified messages.
165
- #
166
- # @example
167
- #
168
- # object.should_receive(:message).with(duck_type(:hello))
169
- # object.should_receive(:message).with(duck_type(:hello, :goodbye))
170
- def duck_type(*args)
171
- DuckTypeMatcher.new(*args)
172
- end
173
-
174
- # Matches a boolean value.
175
- #
176
- # @example
177
- #
178
- # object.should_receive(:message).with(boolean())
179
- def boolean
180
- BooleanMatcher.new(nil)
181
- end
182
-
183
- # Matches a hash that includes the specified key(s) or key/value pairs.
184
- # Ignores any additional keys.
185
- #
186
- # @example
187
- #
188
- # object.should_receive(:message).with(hash_including(:key => val))
189
- # object.should_receive(:message).with(hash_including(:key))
190
- # object.should_receive(:message).with(hash_including(:key, :key2 => val2))
191
- def hash_including(*args)
192
- HashIncludingMatcher.new(anythingize_lonely_keys(*args))
193
- end
194
-
195
- # Matches a hash that doesn't include the specified key(s) or key/value.
196
- #
197
- # @example
198
- #
199
- # object.should_receive(:message).with(hash_excluding(:key => val))
200
- # object.should_receive(:message).with(hash_excluding(:key))
201
- # object.should_receive(:message).with(hash_excluding(:key, :key2 => :val2))
202
- def hash_excluding(*args)
203
- HashExcludingMatcher.new(anythingize_lonely_keys(*args))
204
- end
205
-
206
- alias_method :hash_not_including, :hash_excluding
207
-
208
- # Matches if `arg.instance_of?(klass)`
209
- #
210
- # @example
211
- #
212
- # object.should_receive(:message).with(instance_of(Thing))
213
- def instance_of(klass)
214
- InstanceOf.new(klass)
215
- end
216
-
217
- alias_method :an_instance_of, :instance_of
218
-
219
- # Matches if `arg.kind_of?(klass)`
220
- # @example
221
- #
222
- # object.should_receive(:message).with(kind_of(Thing))
223
- def kind_of(klass)
224
- KindOf.new(klass)
301
+ def description
302
+ "kind of #{@klass.name}"
303
+ end
225
304
  end
226
305
 
227
- alias_method :a_kind_of, :kind_of
228
-
229
- private
230
-
231
- def anythingize_lonely_keys(*args)
232
- hash = args.last.class == Hash ? args.delete_at(-1) : {}
233
- args.each { | arg | hash[arg] = anything }
234
- hash
306
+ matcher_namespace = name + '::'
307
+ ::RSpec::Support.register_matcher_definition do |object|
308
+ # This is the best we have for now. We should tag all of our matchers
309
+ # with a module or something so we can test for it directly.
310
+ #
311
+ # (Note Module#parent in ActiveSupport is defined in a similar way.)
312
+ begin
313
+ object.class.name.include?(matcher_namespace)
314
+ rescue NoMethodError
315
+ # Some objects, like BasicObject, don't implemented standard
316
+ # reflection methods.
317
+ false
318
+ end
235
319
  end
236
320
  end
237
321
  end
@@ -0,0 +1,212 @@
1
+ module RSpec
2
+ module Mocks
3
+ # Provides configuration options for rspec-mocks.
4
+ class Configuration
5
+ def initialize
6
+ @allow_message_expectations_on_nil = nil
7
+ @yield_receiver_to_any_instance_implementation_blocks = true
8
+ @verify_doubled_constant_names = false
9
+ @transfer_nested_constants = false
10
+ @verify_partial_doubles = false
11
+ @temporarily_suppress_partial_double_verification = false
12
+ @color = false
13
+ end
14
+
15
+ # Sets whether RSpec will warn, ignore, or fail a test when
16
+ # expectations are set on nil.
17
+ # By default, when this flag is not set, warning messages are issued when
18
+ # expectations are set on nil. This is to prevent false-positives and to
19
+ # catch potential bugs early on.
20
+ # When set to `true`, warning messages are suppressed.
21
+ # When set to `false`, it will raise an error.
22
+ #
23
+ # @example
24
+ # RSpec.configure do |config|
25
+ # config.mock_with :rspec do |mocks|
26
+ # mocks.allow_message_expectations_on_nil = false
27
+ # end
28
+ # end
29
+ attr_accessor :allow_message_expectations_on_nil
30
+
31
+ def yield_receiver_to_any_instance_implementation_blocks?
32
+ @yield_receiver_to_any_instance_implementation_blocks
33
+ end
34
+
35
+ # Sets whether or not RSpec will yield the receiving instance of a
36
+ # message to blocks that are used for any_instance stub implementations.
37
+ # When set, the first yielded argument will be the receiving instance.
38
+ # Defaults to `true`.
39
+ #
40
+ # @example
41
+ # RSpec.configure do |rspec|
42
+ # rspec.mock_with :rspec do |mocks|
43
+ # mocks.yield_receiver_to_any_instance_implementation_blocks = false
44
+ # end
45
+ # end
46
+ attr_writer :yield_receiver_to_any_instance_implementation_blocks
47
+
48
+ # Adds `stub` and `should_receive` to the given
49
+ # modules or classes. This is usually only necessary
50
+ # if you application uses some proxy classes that
51
+ # "strip themselves down" to a bare minimum set of
52
+ # methods and remove `stub` and `should_receive` in
53
+ # the process.
54
+ #
55
+ # @example
56
+ # RSpec.configure do |rspec|
57
+ # rspec.mock_with :rspec do |mocks|
58
+ # mocks.add_stub_and_should_receive_to Delegator
59
+ # end
60
+ # end
61
+ #
62
+ def add_stub_and_should_receive_to(*modules)
63
+ modules.each do |mod|
64
+ Syntax.enable_should(mod)
65
+ end
66
+ end
67
+
68
+ # Provides the ability to set either `expect`,
69
+ # `should` or both syntaxes. RSpec uses `expect`
70
+ # syntax by default. This is needed if you want to
71
+ # explicitly enable `should` syntax and/or explicitly
72
+ # disable `expect` syntax.
73
+ #
74
+ # @example
75
+ # RSpec.configure do |rspec|
76
+ # rspec.mock_with :rspec do |mocks|
77
+ # mocks.syntax = [:expect, :should]
78
+ # end
79
+ # end
80
+ #
81
+ def syntax=(*values)
82
+ syntaxes = values.flatten
83
+ if syntaxes.include?(:expect)
84
+ Syntax.enable_expect
85
+ else
86
+ Syntax.disable_expect
87
+ end
88
+
89
+ if syntaxes.include?(:should)
90
+ Syntax.enable_should
91
+ else
92
+ Syntax.disable_should
93
+ end
94
+ end
95
+
96
+ # Returns an array with a list of syntaxes
97
+ # that are enabled.
98
+ #
99
+ # @example
100
+ # unless RSpec::Mocks.configuration.syntax.include?(:expect)
101
+ # raise "this RSpec extension gem requires the rspec-mocks `:expect` syntax"
102
+ # end
103
+ #
104
+ def syntax
105
+ syntaxes = []
106
+ syntaxes << :should if Syntax.should_enabled?
107
+ syntaxes << :expect if Syntax.expect_enabled?
108
+ syntaxes
109
+ end
110
+
111
+ def verify_doubled_constant_names?
112
+ !!@verify_doubled_constant_names
113
+ end
114
+
115
+ # When this is set to true, an error will be raised when
116
+ # `instance_double` or `class_double` is given the name of an undefined
117
+ # constant. You probably only want to set this when running your entire
118
+ # test suite, with all production code loaded. Setting this for an
119
+ # isolated unit test will prevent you from being able to isolate it!
120
+ attr_writer :verify_doubled_constant_names
121
+
122
+ # Provides a way to perform customisations when verifying doubles.
123
+ #
124
+ # @example
125
+ # RSpec::Mocks.configuration.before_verifying_doubles do |ref|
126
+ # ref.some_method!
127
+ # end
128
+ def before_verifying_doubles(&block)
129
+ verifying_double_callbacks << block
130
+ end
131
+ alias :when_declaring_verifying_double :before_verifying_doubles
132
+
133
+ # @api private
134
+ # Returns an array of blocks to call when verifying doubles
135
+ def verifying_double_callbacks
136
+ @verifying_double_callbacks ||= []
137
+ end
138
+
139
+ def transfer_nested_constants?
140
+ !!@transfer_nested_constants
141
+ end
142
+
143
+ # Sets the default for the `transfer_nested_constants` option when
144
+ # stubbing constants.
145
+ attr_writer :transfer_nested_constants
146
+
147
+ # When set to true, partial mocks will be verified the same as object
148
+ # doubles. Any stubs will have their arguments checked against the original
149
+ # method, and methods that do not exist cannot be stubbed.
150
+ def verify_partial_doubles=(val)
151
+ @verify_partial_doubles = !!val
152
+ end
153
+
154
+ def verify_partial_doubles?
155
+ @verify_partial_doubles
156
+ end
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
+
163
+ if ::RSpec.respond_to?(:configuration)
164
+ def color?
165
+ ::RSpec.configuration.color_enabled?
166
+ end
167
+ else
168
+ # Indicates whether or not diffs should be colored.
169
+ # Delegates to rspec-core's color option if rspec-core
170
+ # is loaded; otherwise you can set it here.
171
+ attr_writer :color
172
+
173
+ # Indicates whether or not diffs should be colored.
174
+ # Delegates to rspec-core's color option if rspec-core
175
+ # is loaded; otherwise you can set it here.
176
+ def color?
177
+ @color
178
+ end
179
+ end
180
+
181
+ # Monkey-patch `Marshal.dump` to enable dumping of mocked or stubbed
182
+ # objects. By default this will not work since RSpec mocks works by
183
+ # adding singleton methods that cannot be serialized. This patch removes
184
+ # these singleton methods before serialization. Setting to falsey removes
185
+ # the patch.
186
+ #
187
+ # This method is idempotent.
188
+ def patch_marshal_to_support_partial_doubles=(val)
189
+ if val
190
+ RSpec::Mocks::MarshalExtension.patch!
191
+ else
192
+ RSpec::Mocks::MarshalExtension.unpatch!
193
+ end
194
+ end
195
+
196
+ # @api private
197
+ # Resets the configured syntax to the default.
198
+ def reset_syntaxes_to_default
199
+ self.syntax = [:should, :expect]
200
+ RSpec::Mocks::Syntax.warn_about_should!
201
+ end
202
+ end
203
+
204
+ # Mocks specific configuration, as distinct from `RSpec.configuration`
205
+ # which is core RSpec configuration.
206
+ def self.configuration
207
+ @configuration ||= Configuration.new
208
+ end
209
+
210
+ configuration.reset_syntaxes_to_default
211
+ end
212
+ end