rspec-mocks-diag 3.8.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.yardopts +6 -0
  4. data/Changelog.md +1108 -0
  5. data/LICENSE.md +25 -0
  6. data/README.md +460 -0
  7. data/lib/rspec/mocks.rb +130 -0
  8. data/lib/rspec/mocks/any_instance.rb +11 -0
  9. data/lib/rspec/mocks/any_instance/chain.rb +110 -0
  10. data/lib/rspec/mocks/any_instance/error_generator.rb +31 -0
  11. data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +31 -0
  12. data/lib/rspec/mocks/any_instance/expectation_chain.rb +50 -0
  13. data/lib/rspec/mocks/any_instance/message_chains.rb +83 -0
  14. data/lib/rspec/mocks/any_instance/proxy.rb +116 -0
  15. data/lib/rspec/mocks/any_instance/recorder.rb +289 -0
  16. data/lib/rspec/mocks/any_instance/stub_chain.rb +51 -0
  17. data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +23 -0
  18. data/lib/rspec/mocks/argument_list_matcher.rb +100 -0
  19. data/lib/rspec/mocks/argument_matchers.rb +320 -0
  20. data/lib/rspec/mocks/configuration.rb +212 -0
  21. data/lib/rspec/mocks/error_generator.rb +378 -0
  22. data/lib/rspec/mocks/example_methods.rb +434 -0
  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 +132 -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 +748 -0
  32. data/lib/rspec/mocks/method_double.rb +287 -0
  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 +81 -0
  38. data/lib/rspec/mocks/proxy.rb +485 -0
  39. data/lib/rspec/mocks/space.rb +238 -0
  40. data/lib/rspec/mocks/standalone.rb +3 -0
  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 +171 -0
  44. data/lib/rspec/mocks/verifying_double.rb +129 -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 +9 -0
  48. metadata +186 -0
@@ -0,0 +1,238 @@
1
+ RSpec::Support.require_rspec_support 'reentrant_mutex'
2
+
3
+ module RSpec
4
+ module Mocks
5
+ # @private
6
+ # Provides a default space implementation for outside
7
+ # the scope of an example. Called "root" because it serves
8
+ # as the root of the space stack.
9
+ class RootSpace
10
+ def proxy_for(*_args)
11
+ raise_lifecycle_message
12
+ end
13
+
14
+ def any_instance_recorder_for(*_args)
15
+ raise_lifecycle_message
16
+ end
17
+
18
+ def any_instance_proxy_for(*_args)
19
+ raise_lifecycle_message
20
+ end
21
+
22
+ def register_constant_mutator(_mutator)
23
+ raise_lifecycle_message
24
+ end
25
+
26
+ def any_instance_recorders_from_ancestry_of(_object)
27
+ raise_lifecycle_message
28
+ end
29
+
30
+ def reset_all
31
+ end
32
+
33
+ def verify_all
34
+ end
35
+
36
+ def registered?(_object)
37
+ false
38
+ end
39
+
40
+ def superclass_proxy_for(*_args)
41
+ raise_lifecycle_message
42
+ end
43
+
44
+ def new_scope
45
+ Space.new
46
+ end
47
+
48
+ private
49
+
50
+ def raise_lifecycle_message
51
+ raise OutsideOfExampleError,
52
+ "The use of doubles or partial doubles from rspec-mocks outside of the per-test lifecycle is not supported."
53
+ end
54
+ end
55
+
56
+ # @private
57
+ class Space
58
+ attr_reader :proxies, :any_instance_recorders, :proxy_mutex, :any_instance_mutex
59
+
60
+ def initialize
61
+ @proxies = {}
62
+ @any_instance_recorders = {}
63
+ @constant_mutators = []
64
+ @expectation_ordering = OrderGroup.new
65
+ @proxy_mutex = new_mutex
66
+ @any_instance_mutex = new_mutex
67
+ end
68
+
69
+ def new_scope
70
+ NestedSpace.new(self)
71
+ end
72
+
73
+ def verify_all
74
+ proxies.values.each { |proxy| proxy.verify }
75
+ any_instance_recorders.each_value { |recorder| recorder.verify }
76
+ end
77
+
78
+ def reset_all
79
+ proxies.each_value { |proxy| proxy.reset }
80
+ @constant_mutators.reverse.each { |mut| mut.idempotently_reset }
81
+ any_instance_recorders.each_value { |recorder| recorder.stop_all_observation! }
82
+ any_instance_recorders.clear
83
+ end
84
+
85
+ def register_constant_mutator(mutator)
86
+ @constant_mutators << mutator
87
+ end
88
+
89
+ def constant_mutator_for(name)
90
+ @constant_mutators.find { |m| m.full_constant_name == name }
91
+ end
92
+
93
+ def any_instance_recorder_for(klass, only_return_existing=false)
94
+ any_instance_mutex.synchronize do
95
+ id = klass.__id__
96
+ any_instance_recorders.fetch(id) do
97
+ return nil if only_return_existing
98
+ any_instance_recorder_not_found_for(id, klass)
99
+ end
100
+ end
101
+ end
102
+
103
+ def any_instance_proxy_for(klass)
104
+ AnyInstance::Proxy.new(any_instance_recorder_for(klass), proxies_of(klass))
105
+ end
106
+
107
+ def proxies_of(klass)
108
+ proxies.values.select { |proxy| klass === proxy.object }
109
+ end
110
+
111
+ def proxy_for(object)
112
+ proxy_mutex.synchronize do
113
+ id = id_for(object)
114
+ proxies.fetch(id) { proxy_not_found_for(id, object) }
115
+ end
116
+ end
117
+
118
+ def superclass_proxy_for(klass)
119
+ proxy_mutex.synchronize do
120
+ id = id_for(klass)
121
+ proxies.fetch(id) { superclass_proxy_not_found_for(id, klass) }
122
+ end
123
+ end
124
+
125
+ alias ensure_registered proxy_for
126
+
127
+ def registered?(object)
128
+ proxies.key?(id_for object)
129
+ end
130
+
131
+ def any_instance_recorders_from_ancestry_of(object)
132
+ # Optimization: `any_instance` is a feature we generally
133
+ # recommend not using, so we can often early exit here
134
+ # without doing an O(N) linear search over the number of
135
+ # ancestors in the object's class hierarchy.
136
+ return [] if any_instance_recorders.empty?
137
+
138
+ # We access the ancestors through the singleton class, to avoid calling
139
+ # `class` in case `class` has been stubbed.
140
+ (class << object; ancestors; end).map do |klass|
141
+ any_instance_recorders[klass.__id__]
142
+ end.compact
143
+ end
144
+
145
+ private
146
+
147
+ def new_mutex
148
+ Support::ReentrantMutex.new
149
+ end
150
+
151
+ def proxy_not_found_for(id, object)
152
+ proxies[id] = case object
153
+ when NilClass then ProxyForNil.new(@expectation_ordering)
154
+ when TestDouble then object.__build_mock_proxy_unless_expired(@expectation_ordering)
155
+ when Class
156
+ class_proxy_with_callback_verification_strategy(object, CallbackInvocationStrategy.new)
157
+ else
158
+ if RSpec::Mocks.configuration.verify_partial_doubles?
159
+ VerifyingPartialDoubleProxy.new(object, @expectation_ordering)
160
+ else
161
+ PartialDoubleProxy.new(object, @expectation_ordering)
162
+ end
163
+ end
164
+ end
165
+
166
+ def superclass_proxy_not_found_for(id, object)
167
+ raise "superclass_proxy_not_found_for called with something that is not a class" unless Class === object
168
+ proxies[id] = class_proxy_with_callback_verification_strategy(object, NoCallbackInvocationStrategy.new)
169
+ end
170
+
171
+ def class_proxy_with_callback_verification_strategy(object, strategy)
172
+ if RSpec::Mocks.configuration.verify_partial_doubles?
173
+ VerifyingPartialClassDoubleProxy.new(
174
+ self,
175
+ object,
176
+ @expectation_ordering,
177
+ strategy
178
+ )
179
+ else
180
+ PartialClassDoubleProxy.new(self, object, @expectation_ordering)
181
+ end
182
+ end
183
+
184
+ def any_instance_recorder_not_found_for(id, klass)
185
+ any_instance_recorders[id] = AnyInstance::Recorder.new(klass)
186
+ end
187
+
188
+ if defined?(::BasicObject) && !::BasicObject.method_defined?(:__id__) # for 1.9.2
189
+ require 'securerandom'
190
+
191
+ def id_for(object)
192
+ id = object.__id__
193
+
194
+ return id if object.equal?(::ObjectSpace._id2ref(id))
195
+ # this suggests that object.__id__ is proxying through to some wrapped object
196
+
197
+ object.instance_exec do
198
+ @__id_for_rspec_mocks_space ||= ::SecureRandom.uuid
199
+ end
200
+ end
201
+ else
202
+ def id_for(object)
203
+ object.__id__
204
+ end
205
+ end
206
+ end
207
+
208
+ # @private
209
+ class NestedSpace < Space
210
+ def initialize(parent)
211
+ @parent = parent
212
+ super()
213
+ end
214
+
215
+ def proxies_of(klass)
216
+ super + @parent.proxies_of(klass)
217
+ end
218
+
219
+ def constant_mutator_for(name)
220
+ super || @parent.constant_mutator_for(name)
221
+ end
222
+
223
+ def registered?(object)
224
+ super || @parent.registered?(object)
225
+ end
226
+
227
+ private
228
+
229
+ def proxy_not_found_for(id, object)
230
+ @parent.proxies[id] || super
231
+ end
232
+
233
+ def any_instance_recorder_not_found_for(id, klass)
234
+ @parent.any_instance_recorders[id] || super
235
+ end
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,3 @@
1
+ require 'rspec/mocks'
2
+ extend RSpec::Mocks::ExampleMethods
3
+ RSpec::Mocks.setup
@@ -0,0 +1,325 @@
1
+ module RSpec
2
+ module Mocks
3
+ # @api private
4
+ # Provides methods for enabling and disabling the available syntaxes
5
+ # provided by rspec-mocks.
6
+ module Syntax
7
+ # @private
8
+ def self.warn_about_should!
9
+ @warn_about_should = true
10
+ end
11
+
12
+ # @private
13
+ def self.warn_unless_should_configured(method_name , replacement="the new `:expect` syntax or explicitly enable `:should`")
14
+ if @warn_about_should
15
+ RSpec.deprecate(
16
+ "Using `#{method_name}` from rspec-mocks' old `:should` syntax without explicitly enabling the syntax",
17
+ :replacement => replacement
18
+ )
19
+
20
+ @warn_about_should = false
21
+ end
22
+ end
23
+
24
+ # @api private
25
+ # Enables the should syntax (`dbl.stub`, `dbl.should_receive`, etc).
26
+ def self.enable_should(syntax_host=default_should_syntax_host)
27
+ @warn_about_should = false if syntax_host == default_should_syntax_host
28
+ return if should_enabled?(syntax_host)
29
+
30
+ syntax_host.class_exec do
31
+ def should_receive(message, opts={}, &block)
32
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
33
+ ::RSpec::Mocks.expect_message(self, message, opts, &block)
34
+ end
35
+
36
+ def should_not_receive(message, &block)
37
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
38
+ ::RSpec::Mocks.expect_message(self, message, {}, &block).never
39
+ end
40
+
41
+ def stub(message_or_hash, opts={}, &block)
42
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
43
+ if ::Hash === message_or_hash
44
+ message_or_hash.each { |message, value| stub(message).and_return value }
45
+ else
46
+ ::RSpec::Mocks.allow_message(self, message_or_hash, opts, &block)
47
+ end
48
+ end
49
+
50
+ def unstub(message)
51
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__, "`allow(...).to receive(...).and_call_original` or explicitly enable `:should`")
52
+ ::RSpec::Mocks.space.proxy_for(self).remove_stub(message)
53
+ end
54
+
55
+ def stub_chain(*chain, &blk)
56
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
57
+ ::RSpec::Mocks::StubChain.stub_chain_on(self, *chain, &blk)
58
+ end
59
+
60
+ def as_null_object
61
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
62
+ @_null_object = true
63
+ ::RSpec::Mocks.space.proxy_for(self).as_null_object
64
+ end
65
+
66
+ def null_object?
67
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
68
+ defined?(@_null_object)
69
+ end
70
+
71
+ def received_message?(message, *args, &block)
72
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
73
+ ::RSpec::Mocks.space.proxy_for(self).received_message?(message, *args, &block)
74
+ end
75
+
76
+ unless Class.respond_to? :any_instance
77
+ Class.class_exec do
78
+ def any_instance
79
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
80
+ ::RSpec::Mocks.space.any_instance_proxy_for(self)
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ # @api private
88
+ # Disables the should syntax (`dbl.stub`, `dbl.should_receive`, etc).
89
+ def self.disable_should(syntax_host=default_should_syntax_host)
90
+ return unless should_enabled?(syntax_host)
91
+
92
+ syntax_host.class_exec do
93
+ undef should_receive
94
+ undef should_not_receive
95
+ undef stub
96
+ undef unstub
97
+ undef stub_chain
98
+ undef as_null_object
99
+ undef null_object?
100
+ undef received_message?
101
+ end
102
+
103
+ Class.class_exec do
104
+ undef any_instance
105
+ end
106
+ end
107
+
108
+ # @api private
109
+ # Enables the expect syntax (`expect(dbl).to receive`, `allow(dbl).to receive`, etc).
110
+ def self.enable_expect(syntax_host=::RSpec::Mocks::ExampleMethods)
111
+ return if expect_enabled?(syntax_host)
112
+
113
+ syntax_host.class_exec do
114
+ def receive(method_name, &block)
115
+ Matchers::Receive.new(method_name, block)
116
+ end
117
+
118
+ def receive_messages(message_return_value_hash)
119
+ matcher = Matchers::ReceiveMessages.new(message_return_value_hash)
120
+ matcher.warn_about_block if block_given?
121
+ matcher
122
+ end
123
+
124
+ def receive_message_chain(*messages, &block)
125
+ Matchers::ReceiveMessageChain.new(messages, &block)
126
+ end
127
+
128
+ def allow(target)
129
+ AllowanceTarget.new(target)
130
+ end
131
+
132
+ def expect_any_instance_of(klass)
133
+ AnyInstanceExpectationTarget.new(klass)
134
+ end
135
+
136
+ def allow_any_instance_of(klass)
137
+ AnyInstanceAllowanceTarget.new(klass)
138
+ end
139
+ end
140
+
141
+ RSpec::Mocks::ExampleMethods::ExpectHost.class_exec do
142
+ def expect(target)
143
+ ExpectationTarget.new(target)
144
+ end
145
+ end
146
+ end
147
+
148
+ # @api private
149
+ # Disables the expect syntax (`expect(dbl).to receive`, `allow(dbl).to receive`, etc).
150
+ def self.disable_expect(syntax_host=::RSpec::Mocks::ExampleMethods)
151
+ return unless expect_enabled?(syntax_host)
152
+
153
+ syntax_host.class_exec do
154
+ undef receive
155
+ undef receive_messages
156
+ undef receive_message_chain
157
+ undef allow
158
+ undef expect_any_instance_of
159
+ undef allow_any_instance_of
160
+ end
161
+
162
+ RSpec::Mocks::ExampleMethods::ExpectHost.class_exec do
163
+ undef expect
164
+ end
165
+ end
166
+
167
+ # @api private
168
+ # Indicates whether or not the should syntax is enabled.
169
+ def self.should_enabled?(syntax_host=default_should_syntax_host)
170
+ syntax_host.method_defined?(:should_receive)
171
+ end
172
+
173
+ # @api private
174
+ # Indicates whether or not the expect syntax is enabled.
175
+ def self.expect_enabled?(syntax_host=::RSpec::Mocks::ExampleMethods)
176
+ syntax_host.method_defined?(:allow)
177
+ end
178
+
179
+ # @api private
180
+ # Determines where the methods like `should_receive`, and `stub` are added.
181
+ def self.default_should_syntax_host
182
+ # JRuby 1.7.4 introduces a regression whereby `defined?(::BasicObject) => nil`
183
+ # yet `BasicObject` still exists and patching onto ::Object breaks things
184
+ # e.g. SimpleDelegator expectations won't work
185
+ #
186
+ # See: https://github.com/jruby/jruby/issues/814
187
+ if defined?(JRUBY_VERSION) && JRUBY_VERSION == '1.7.4' && RUBY_VERSION.to_f > 1.8
188
+ return ::BasicObject
189
+ end
190
+
191
+ # On 1.8.7, Object.ancestors.last == Kernel but
192
+ # things blow up if we include `RSpec::Mocks::Methods`
193
+ # into Kernel...not sure why.
194
+ return Object unless defined?(::BasicObject)
195
+
196
+ # MacRuby has BasicObject but it's not the root class.
197
+ return Object unless Object.ancestors.last == ::BasicObject
198
+
199
+ ::BasicObject
200
+ end
201
+ end
202
+ end
203
+ end
204
+
205
+ if defined?(BasicObject)
206
+ # The legacy `:should` syntax adds the following methods directly to
207
+ # `BasicObject` so that they are available off of any object. Note, however,
208
+ # that this syntax does not always play nice with delegate/proxy objects.
209
+ # We recommend you use the non-monkeypatching `:expect` syntax instead.
210
+ # @see Class
211
+ class BasicObject
212
+ # @method should_receive
213
+ # Sets an expectation that this object should receive a message before
214
+ # the end of the example.
215
+ #
216
+ # @example
217
+ # logger = double('logger')
218
+ # thing_that_logs = ThingThatLogs.new(logger)
219
+ # logger.should_receive(:log)
220
+ # thing_that_logs.do_something_that_logs_a_message
221
+ #
222
+ # @note This is only available when you have enabled the `should` syntax.
223
+ # @see RSpec::Mocks::ExampleMethods#expect
224
+
225
+ # @method should_not_receive
226
+ # Sets and expectation that this object should _not_ receive a message
227
+ # during this example.
228
+ # @see RSpec::Mocks::ExampleMethods#expect
229
+
230
+ # @method stub
231
+ # Tells the object to respond to the message with the specified value.
232
+ #
233
+ # @example
234
+ # counter.stub(:count).and_return(37)
235
+ # counter.stub(:count => 37)
236
+ # counter.stub(:count) { 37 }
237
+ #
238
+ # @note This is only available when you have enabled the `should` syntax.
239
+ # @see RSpec::Mocks::ExampleMethods#allow
240
+
241
+ # @method unstub
242
+ # Removes a stub. On a double, the object will no longer respond to
243
+ # `message`. On a real object, the original method (if it exists) is
244
+ # restored.
245
+ #
246
+ # This is rarely used, but can be useful when a stub is set up during a
247
+ # shared `before` hook for the common case, but you want to replace it
248
+ # for a special case.
249
+ #
250
+ # @note This is only available when you have enabled the `should` syntax.
251
+
252
+ # @method stub_chain
253
+ # @overload stub_chain(method1, method2)
254
+ # @overload stub_chain("method1.method2")
255
+ # @overload stub_chain(method1, method_to_value_hash)
256
+ #
257
+ # Stubs a chain of methods.
258
+ #
259
+ # ## Warning:
260
+ #
261
+ # Chains can be arbitrarily long, which makes it quite painless to
262
+ # violate the Law of Demeter in violent ways, so you should consider any
263
+ # use of `stub_chain` a code smell. Even though not all code smells
264
+ # indicate real problems (think fluent interfaces), `stub_chain` still
265
+ # results in brittle examples. For example, if you write
266
+ # `foo.stub_chain(:bar, :baz => 37)` in a spec and then the
267
+ # implementation calls `foo.baz.bar`, the stub will not work.
268
+ #
269
+ # @example
270
+ # double.stub_chain("foo.bar") { :baz }
271
+ # double.stub_chain(:foo, :bar => :baz)
272
+ # double.stub_chain(:foo, :bar) { :baz }
273
+ #
274
+ # # Given any of ^^ these three forms ^^:
275
+ # double.foo.bar # => :baz
276
+ #
277
+ # # Common use in Rails/ActiveRecord:
278
+ # Article.stub_chain("recent.published") { [Article.new] }
279
+ #
280
+ # @note This is only available when you have enabled the `should` syntax.
281
+ # @see RSpec::Mocks::ExampleMethods#receive_message_chain
282
+
283
+ # @method as_null_object
284
+ # Tells the object to respond to all messages. If specific stub values
285
+ # are declared, they'll work as expected. If not, the receiver is
286
+ # returned.
287
+ #
288
+ # @note This is only available when you have enabled the `should` syntax.
289
+
290
+ # @method null_object?
291
+ # Returns true if this object has received `as_null_object`
292
+ #
293
+ # @note This is only available when you have enabled the `should` syntax.
294
+ end
295
+ end
296
+
297
+ # The legacy `:should` syntax adds the `any_instance` to `Class`.
298
+ # We generally recommend you use the newer `:expect` syntax instead,
299
+ # which allows you to stub any instance of a class using
300
+ # `allow_any_instance_of(klass)` or mock any instance using
301
+ # `expect_any_instance_of(klass)`.
302
+ # @see BasicObject
303
+ class Class
304
+ # @method any_instance
305
+ # Used to set stubs and message expectations on any instance of a given
306
+ # class. Returns a [Recorder](Recorder), which records messages like
307
+ # `stub` and `should_receive` for later playback on instances of the
308
+ # class.
309
+ #
310
+ # @example
311
+ # Car.any_instance.should_receive(:go)
312
+ # race = Race.new
313
+ # race.cars << Car.new
314
+ # race.go # assuming this delegates to all of its cars
315
+ # # this example would pass
316
+ #
317
+ # Account.any_instance.stub(:balance) { Money.new(:USD, 25) }
318
+ # Account.new.balance # => Money.new(:USD, 25))
319
+ #
320
+ # @return [Recorder]
321
+ #
322
+ # @note This is only available when you have enabled the `should` syntax.
323
+ # @see RSpec::Mocks::ExampleMethods#expect_any_instance_of
324
+ # @see RSpec::Mocks::ExampleMethods#allow_any_instance_of
325
+ end