rspec-mocks 3.0.4 → 3.12.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.document +1 -1
  4. data/.yardopts +1 -1
  5. data/Changelog.md +512 -2
  6. data/{License.txt → LICENSE.md} +5 -4
  7. data/README.md +113 -30
  8. data/lib/rspec/mocks/any_instance/chain.rb +5 -3
  9. data/lib/rspec/mocks/any_instance/error_generator.rb +31 -0
  10. data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +1 -5
  11. data/lib/rspec/mocks/any_instance/expectation_chain.rb +9 -8
  12. data/lib/rspec/mocks/any_instance/message_chains.rb +7 -8
  13. data/lib/rspec/mocks/any_instance/proxy.rb +14 -5
  14. data/lib/rspec/mocks/any_instance/recorder.rb +61 -31
  15. data/lib/rspec/mocks/any_instance/stub_chain.rb +15 -11
  16. data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +1 -5
  17. data/lib/rspec/mocks/any_instance.rb +1 -0
  18. data/lib/rspec/mocks/argument_list_matcher.rb +55 -10
  19. data/lib/rspec/mocks/argument_matchers.rb +88 -30
  20. data/lib/rspec/mocks/configuration.rb +61 -13
  21. data/lib/rspec/mocks/error_generator.rb +250 -107
  22. data/lib/rspec/mocks/example_methods.rb +151 -28
  23. data/lib/rspec/mocks/instance_method_stasher.rb +17 -6
  24. data/lib/rspec/mocks/matchers/have_received.rb +50 -20
  25. data/lib/rspec/mocks/matchers/receive.rb +39 -11
  26. data/lib/rspec/mocks/matchers/receive_message_chain.rb +22 -7
  27. data/lib/rspec/mocks/matchers/receive_messages.rb +12 -7
  28. data/lib/rspec/mocks/message_chain.rb +3 -7
  29. data/lib/rspec/mocks/message_expectation.rb +466 -307
  30. data/lib/rspec/mocks/method_double.rb +88 -29
  31. data/lib/rspec/mocks/method_reference.rb +85 -25
  32. data/lib/rspec/mocks/minitest_integration.rb +68 -0
  33. data/lib/rspec/mocks/mutate_const.rb +50 -109
  34. data/lib/rspec/mocks/object_reference.rb +89 -32
  35. data/lib/rspec/mocks/order_group.rb +4 -5
  36. data/lib/rspec/mocks/proxy.rb +156 -60
  37. data/lib/rspec/mocks/space.rb +52 -35
  38. data/lib/rspec/mocks/standalone.rb +1 -1
  39. data/lib/rspec/mocks/syntax.rb +26 -30
  40. data/lib/rspec/mocks/targets.rb +55 -28
  41. data/lib/rspec/mocks/test_double.rb +43 -7
  42. data/lib/rspec/mocks/verifying_double.rb +27 -33
  43. data/lib/rspec/mocks/{verifying_message_expecation.rb → verifying_message_expectation.rb} +11 -16
  44. data/lib/rspec/mocks/verifying_proxy.rb +77 -26
  45. data/lib/rspec/mocks/version.rb +1 -1
  46. data/lib/rspec/mocks.rb +8 -1
  47. data.tar.gz.sig +0 -0
  48. metadata +80 -43
  49. metadata.gz.sig +0 -0
@@ -3,7 +3,6 @@ module RSpec
3
3
  module AnyInstance
4
4
  # @private
5
5
  class StubChain < Chain
6
-
7
6
  # @private
8
7
  def expectation_fulfilled?
9
8
  true
@@ -26,20 +25,25 @@ module RSpec
26
25
  stub
27
26
  end
28
27
 
29
- def invocation_order
30
- @invocation_order ||= {
31
- :with => [nil],
28
+ InvocationOrder =
29
+ {
32
30
  :and_return => [:with, nil],
33
31
  :and_raise => [:with, nil],
34
- :and_yield => [:with, nil],
35
- :and_call_original => [:with, nil]
36
- }
32
+ :and_yield => [:with, :and_yield, nil],
33
+ :and_throw => [:with, nil],
34
+ :and_call_original => [:with, nil],
35
+ :and_wrap_original => [:with, nil]
36
+ }.freeze
37
+
38
+ EmptyInvocationOrder = {}.freeze
39
+
40
+ def invocation_order
41
+ InvocationOrder
37
42
  end
38
43
 
39
- def verify_invocation_order(rspec_method_name, *args, &block)
40
- unless invocation_order[rspec_method_name].include?(last_message)
41
- raise(NoMethodError, "Undefined method #{rspec_method_name}")
42
- end
44
+ def verify_invocation_order(rspec_method_name, *_args, &_block)
45
+ return if invocation_order.fetch(rspec_method_name, [nil]).include?(last_message)
46
+ raise NoMethodError, "Undefined method #{rspec_method_name}"
43
47
  end
44
48
  end
45
49
  end
@@ -15,11 +15,7 @@ module RSpec
15
15
  end
16
16
 
17
17
  def invocation_order
18
- @invocation_order ||= {
19
- :and_return => [nil],
20
- :and_raise => [nil],
21
- :and_yield => [nil]
22
- }
18
+ EmptyInvocationOrder
23
19
  end
24
20
  end
25
21
  end
@@ -1,5 +1,6 @@
1
1
  %w[
2
2
  any_instance/chain
3
+ any_instance/error_generator
3
4
  any_instance/stub_chain
4
5
  any_instance/stub_chain_chain
5
6
  any_instance/expect_chain_chain
@@ -44,29 +44,74 @@ module RSpec
44
44
  # @see #args_match?
45
45
  def initialize(*expected_args)
46
46
  @expected_args = expected_args
47
-
48
- @matchers = case expected_args.first
49
- when ArgumentMatchers::AnyArgsMatcher then Array
50
- when ArgumentMatchers::NoArgsMatcher then []
51
- else expected_args
52
- end
47
+ ensure_expected_args_valid!
53
48
  end
49
+ ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true)
54
50
 
55
51
  # @api public
56
- # @param [Array] args
52
+ # @param [Array] actual_args
57
53
  #
58
54
  # Matches each element in the `expected_args` against the element in the same
59
55
  # position of the arguments passed to `new`.
60
56
  #
61
57
  # @see #initialize
62
- def args_match?(*args)
63
- Support::FuzzyMatcher.values_match?(@matchers, args)
58
+ def args_match?(*actual_args)
59
+ expected_args = resolve_expected_args_based_on(actual_args)
60
+
61
+ return false if expected_args.size != actual_args.size
62
+
63
+ if RUBY_VERSION >= "3"
64
+ # If the expectation was set with keywords, while the actual method was called with a positional hash argument, they don't match.
65
+ # If the expectation was set without keywords, e.g., with({a: 1}), then it fine to call it with either foo(a: 1) or foo({a: 1}).
66
+ # This corresponds to Ruby semantics, as if the method was def foo(options).
67
+ if Hash === expected_args.last && Hash === actual_args.last
68
+ if !Hash.ruby2_keywords_hash?(actual_args.last) && Hash.ruby2_keywords_hash?(expected_args.last)
69
+ return false
70
+ end
71
+ end
72
+ end
73
+
74
+ Support::FuzzyMatcher.values_match?(expected_args, actual_args)
75
+ end
76
+ ruby2_keywords :args_match? if respond_to?(:ruby2_keywords, true)
77
+
78
+ # @private
79
+ # Resolves abstract arg placeholders like `no_args` and `any_args` into
80
+ # a more concrete arg list based on the provided `actual_args`.
81
+ def resolve_expected_args_based_on(actual_args)
82
+ return [] if [ArgumentMatchers::NoArgsMatcher::INSTANCE] == expected_args
83
+
84
+ any_args_index = expected_args.index { |a| ArgumentMatchers::AnyArgsMatcher::INSTANCE == a }
85
+ return expected_args unless any_args_index
86
+
87
+ replace_any_args_with_splat_of_anything(any_args_index, actual_args.count)
88
+ end
89
+
90
+ private
91
+
92
+ def replace_any_args_with_splat_of_anything(before_count, actual_args_count)
93
+ any_args_count = actual_args_count - expected_args.count + 1
94
+ after_count = expected_args.count - before_count - 1
95
+
96
+ any_args = 1.upto(any_args_count).map { ArgumentMatchers::AnyArgMatcher::INSTANCE }
97
+ expected_args.first(before_count) + any_args + expected_args.last(after_count)
98
+ end
99
+
100
+ def ensure_expected_args_valid!
101
+ if expected_args.count { |a| ArgumentMatchers::AnyArgsMatcher::INSTANCE == a } > 1
102
+ raise ArgumentError, "`any_args` can only be passed to " \
103
+ "`with` once but you have passed it multiple times."
104
+ elsif expected_args.count > 1 && expected_args.any? { |a| ArgumentMatchers::NoArgsMatcher::INSTANCE == a }
105
+ raise ArgumentError, "`no_args` can only be passed as a " \
106
+ "singleton argument to `with` (i.e. `with(no_args)`), " \
107
+ "but you have passed additional arguments."
108
+ end
64
109
  end
65
110
 
66
111
  # Value that will match all argument lists.
67
112
  #
68
113
  # @private
69
- MATCH_ALL = new(ArgumentMatchers::AnyArgsMatcher.new)
114
+ MATCH_ALL = new(ArgumentMatchers::AnyArgsMatcher::INSTANCE)
70
115
  end
71
116
  end
72
117
  end
@@ -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,38 +14,38 @@ module RSpec
10
14
  #
11
15
  # @see ArgumentListMatcher
12
16
  module ArgumentMatchers
13
- # Matches any args at all. Supports a more explicit variation of
14
- # `expect(object).to receive(:message)`
17
+ # Acts like an arg splat, matching any number of args at any point in an arg list.
15
18
  #
16
19
  # @example
20
+ # expect(object).to receive(:message).with(1, 2, any_args)
17
21
  #
18
- # expect(object).to receive(:message).with(any_args)
22
+ # # matches any of these:
23
+ # object.message(1, 2)
24
+ # object.message(1, 2, 3)
25
+ # object.message(1, 2, 3, 4)
19
26
  def any_args
20
- AnyArgsMatcher.new
27
+ AnyArgsMatcher::INSTANCE
21
28
  end
22
29
 
23
30
  # Matches any argument at all.
24
31
  #
25
32
  # @example
26
- #
27
33
  # expect(object).to receive(:message).with(anything)
28
34
  def anything
29
- AnyArgMatcher.new
35
+ AnyArgMatcher::INSTANCE
30
36
  end
31
37
 
32
38
  # Matches no arguments.
33
39
  #
34
40
  # @example
35
- #
36
41
  # expect(object).to receive(:message).with(no_args)
37
42
  def no_args
38
- NoArgsMatcher.new
43
+ NoArgsMatcher::INSTANCE
39
44
  end
40
45
 
41
46
  # Matches if the actual argument responds to the specified messages.
42
47
  #
43
48
  # @example
44
- #
45
49
  # expect(object).to receive(:message).with(duck_type(:hello))
46
50
  # expect(object).to receive(:message).with(duck_type(:hello, :goodbye))
47
51
  def duck_type(*args)
@@ -51,17 +55,15 @@ module RSpec
51
55
  # Matches a boolean value.
52
56
  #
53
57
  # @example
54
- #
55
58
  # expect(object).to receive(:message).with(boolean())
56
59
  def boolean
57
- BooleanMatcher.new
60
+ BooleanMatcher::INSTANCE
58
61
  end
59
62
 
60
63
  # Matches a hash that includes the specified key(s) or key/value pairs.
61
64
  # Ignores any additional keys.
62
65
  #
63
66
  # @example
64
- #
65
67
  # expect(object).to receive(:message).with(hash_including(:key => val))
66
68
  # expect(object).to receive(:message).with(hash_including(:key))
67
69
  # expect(object).to receive(:message).with(hash_including(:key, :key2 => val2))
@@ -73,7 +75,6 @@ module RSpec
73
75
  # Ignores duplicates and additional values
74
76
  #
75
77
  # @example
76
- #
77
78
  # expect(object).to receive(:message).with(array_including(1,2,3))
78
79
  # expect(object).to receive(:message).with(array_including([1,2,3]))
79
80
  def array_including(*args)
@@ -84,7 +85,6 @@ module RSpec
84
85
  # Matches a hash that doesn't include the specified key(s) or key/value.
85
86
  #
86
87
  # @example
87
- #
88
88
  # expect(object).to receive(:message).with(hash_excluding(:key => val))
89
89
  # expect(object).to receive(:message).with(hash_excluding(:key))
90
90
  # expect(object).to receive(:message).with(hash_excluding(:key, :key2 => :val2))
@@ -97,7 +97,6 @@ module RSpec
97
97
  # Matches if `arg.instance_of?(klass)`
98
98
  #
99
99
  # @example
100
- #
101
100
  # expect(object).to receive(:message).with(instance_of(Thing))
102
101
  def instance_of(klass)
103
102
  InstanceOf.new(klass)
@@ -106,8 +105,8 @@ module RSpec
106
105
  alias_method :an_instance_of, :instance_of
107
106
 
108
107
  # Matches if `arg.kind_of?(klass)`
109
- # @example
110
108
  #
109
+ # @example
111
110
  # expect(object).to receive(:message).with(kind_of(Thing))
112
111
  def kind_of(klass)
113
112
  KindOf.new(klass)
@@ -117,21 +116,38 @@ module RSpec
117
116
 
118
117
  # @private
119
118
  def self.anythingize_lonely_keys(*args)
120
- hash = args.last.class == Hash ? args.delete_at(-1) : {}
121
- args.each { | arg | hash[arg] = AnyArgMatcher.new }
119
+ hash = Hash === args.last ? args.delete_at(-1) : {}
120
+ args.each { | arg | hash[arg] = AnyArgMatcher::INSTANCE }
122
121
  hash
123
122
  end
124
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))
138
+ end
139
+ end
140
+
125
141
  # @private
126
- class AnyArgsMatcher
142
+ class AnyArgsMatcher < SingletonMatcher
127
143
  def description
128
- "any args"
144
+ "*(any args)"
129
145
  end
130
146
  end
131
147
 
132
148
  # @private
133
- class AnyArgMatcher
134
- def ===(other)
149
+ class AnyArgMatcher < SingletonMatcher
150
+ def ===(_other)
135
151
  true
136
152
  end
137
153
 
@@ -141,14 +157,14 @@ module RSpec
141
157
  end
142
158
 
143
159
  # @private
144
- class NoArgsMatcher
160
+ class NoArgsMatcher < SingletonMatcher
145
161
  def description
146
162
  "no args"
147
163
  end
148
164
  end
149
165
 
150
166
  # @private
151
- class BooleanMatcher
167
+ class BooleanMatcher < SingletonMatcher
152
168
  def ===(value)
153
169
  true == value || false == value
154
170
  end
@@ -166,14 +182,27 @@ module RSpec
166
182
 
167
183
  def ===(predicate, actual)
168
184
  @expected.__send__(predicate) do |k, v|
169
- actual.has_key?(k) && Support::FuzzyMatcher.values_match?(v, actual[k])
185
+ actual.key?(k) && Support::FuzzyMatcher.values_match?(v, actual[k])
170
186
  end
171
187
  rescue NoMethodError
172
188
  false
173
189
  end
174
190
 
175
191
  def description(name)
176
- "#{name}(#{@expected.inspect.sub(/^\{/,"").sub(/\}$/,"")})"
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
+ ]
177
206
  end
178
207
  end
179
208
 
@@ -206,11 +235,26 @@ module RSpec
206
235
  end
207
236
 
208
237
  def ===(actual)
209
- Set.new(actual).superset?(Set.new(@expected))
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
244
+ rescue NoMethodError
245
+ false
210
246
  end
211
247
 
212
248
  def description
213
- "array_including(#{@expected.join(", ")})"
249
+ "array_including(#{formatted_expected_values})"
250
+ end
251
+
252
+ private
253
+
254
+ def formatted_expected_values
255
+ @expected.map do |x|
256
+ RSpec::Support.rspec_description_for_object(x)
257
+ end.join(", ")
214
258
  end
215
259
  end
216
260
 
@@ -221,7 +265,7 @@ module RSpec
221
265
  end
222
266
 
223
267
  def ===(value)
224
- @methods_to_respond_to.all? {|message| value.respond_to?(message)}
268
+ @methods_to_respond_to.all? { |message| value.respond_to?(message) }
225
269
  end
226
270
 
227
271
  def description
@@ -259,6 +303,20 @@ module RSpec
259
303
  end
260
304
  end
261
305
 
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
319
+ end
262
320
  end
263
321
  end
264
322
  end
@@ -2,14 +2,32 @@ module RSpec
2
2
  module Mocks
3
3
  # Provides configuration options for rspec-mocks.
4
4
  class Configuration
5
-
6
5
  def initialize
6
+ @allow_message_expectations_on_nil = nil
7
7
  @yield_receiver_to_any_instance_implementation_blocks = true
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
 
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
+
13
31
  def yield_receiver_to_any_instance_implementation_blocks?
14
32
  @yield_receiver_to_any_instance_implementation_blocks
15
33
  end
@@ -20,15 +38,12 @@ module RSpec
20
38
  # Defaults to `true`.
21
39
  #
22
40
  # @example
23
- #
24
41
  # RSpec.configure do |rspec|
25
42
  # rspec.mock_with :rspec do |mocks|
26
43
  # mocks.yield_receiver_to_any_instance_implementation_blocks = false
27
44
  # end
28
45
  # end
29
- def yield_receiver_to_any_instance_implementation_blocks=(arg)
30
- @yield_receiver_to_any_instance_implementation_blocks = arg
31
- end
46
+ attr_writer :yield_receiver_to_any_instance_implementation_blocks
32
47
 
33
48
  # Adds `stub` and `should_receive` to the given
34
49
  # modules or classes. This is usually only necessary
@@ -38,7 +53,6 @@ module RSpec
38
53
  # the process.
39
54
  #
40
55
  # @example
41
- #
42
56
  # RSpec.configure do |rspec|
43
57
  # rspec.mock_with :rspec do |mocks|
44
58
  # mocks.add_stub_and_should_receive_to Delegator
@@ -58,7 +72,6 @@ module RSpec
58
72
  # disable `expect` syntax.
59
73
  #
60
74
  # @example
61
- #
62
75
  # RSpec.configure do |rspec|
63
76
  # rspec.mock_with :rspec do |mocks|
64
77
  # mocks.syntax = [:expect, :should]
@@ -84,7 +97,6 @@ module RSpec
84
97
  # that are enabled.
85
98
  #
86
99
  # @example
87
- #
88
100
  # unless RSpec::Mocks.configuration.syntax.include?(:expect)
89
101
  # raise "this RSpec extension gem requires the rspec-mocks `:expect` syntax"
90
102
  # end
@@ -105,8 +117,23 @@ module RSpec
105
117
  # constant. You probably only want to set this when running your entire
106
118
  # test suite, with all production code loaded. Setting this for an
107
119
  # isolated unit test will prevent you from being able to isolate it!
108
- def verify_doubled_constant_names=(val)
109
- @verify_doubled_constant_names = val
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 ||= []
110
137
  end
111
138
 
112
139
  def transfer_nested_constants?
@@ -115,9 +142,7 @@ module RSpec
115
142
 
116
143
  # Sets the default for the `transfer_nested_constants` option when
117
144
  # stubbing constants.
118
- def transfer_nested_constants=(val)
119
- @transfer_nested_constants = val
120
- end
145
+ attr_writer :transfer_nested_constants
121
146
 
122
147
  # When set to true, partial mocks will be verified the same as object
123
148
  # doubles. Any stubs will have their arguments checked against the original
@@ -130,6 +155,29 @@ module RSpec
130
155
  @verify_partial_doubles
131
156
  end
132
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
+
133
181
  # Monkey-patch `Marshal.dump` to enable dumping of mocked or stubbed
134
182
  # objects. By default this will not work since RSpec mocks works by
135
183
  # adding singleton methods that cannot be serialized. This patch removes