rspec-mocks 2.99.4 → 3.0.0.beta1

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 (133) hide show
  1. checksums.yaml +14 -6
  2. checksums.yaml.gz.sig +2 -0
  3. data.tar.gz.sig +1 -0
  4. data/Changelog.md +89 -105
  5. data/License.txt +1 -0
  6. data/README.md +77 -57
  7. data/features/argument_matchers/explicit.feature +5 -5
  8. data/features/argument_matchers/general_matchers.feature +10 -10
  9. data/features/argument_matchers/type_matchers.feature +3 -3
  10. data/features/message_expectations/allow_any_instance_of.feature +1 -1
  11. data/features/message_expectations/any_instance.feature +27 -5
  12. data/features/message_expectations/call_original.feature +2 -2
  13. data/features/message_expectations/expect_message_using_expect.feature +2 -2
  14. data/features/message_expectations/expect_message_using_should_receive.feature +2 -2
  15. data/features/message_expectations/receive_counts.feature +7 -7
  16. data/features/message_expectations/warn_when_expectation_is_set_on_nil.feature +3 -3
  17. data/features/method_stubs/README.md +3 -0
  18. data/features/method_stubs/any_instance.feature +11 -11
  19. data/features/method_stubs/as_null_object.feature +4 -4
  20. data/features/method_stubs/simple_return_value_with_stub.feature +7 -7
  21. data/features/method_stubs/stub_chain.feature +3 -3
  22. data/features/method_stubs/stub_implementation.feature +2 -2
  23. data/features/method_stubs/to_ary.feature +2 -2
  24. data/features/mutating_constants/hiding_defined_constant.feature +2 -2
  25. data/features/mutating_constants/stub_defined_constant.feature +5 -5
  26. data/features/mutating_constants/stub_undefined_constant.feature +6 -6
  27. data/features/outside_rspec/configuration.feature +0 -2
  28. data/features/outside_rspec/standalone.feature +1 -1
  29. data/features/spies/spy_partial_mock_method.feature +2 -2
  30. data/features/spies/spy_pure_mock_method.feature +5 -5
  31. data/features/spies/spy_unstubbed_method.feature +1 -1
  32. data/features/support/env.rb +10 -1
  33. data/features/test_frameworks/test_unit.feature +1 -1
  34. data/features/verifying_doubles/class_doubles.feature +88 -0
  35. data/features/verifying_doubles/dynamic_classes.feature +72 -0
  36. data/features/verifying_doubles/introduction.feature +85 -0
  37. data/features/verifying_doubles/object_doubles.feature +65 -0
  38. data/features/verifying_doubles/partial_doubles.feature +34 -0
  39. data/lib/rspec/mocks.rb +8 -34
  40. data/lib/rspec/mocks/any_instance/chain.rb +4 -34
  41. data/lib/rspec/mocks/any_instance/expectation_chain.rb +14 -4
  42. data/lib/rspec/mocks/any_instance/message_chains.rb +27 -12
  43. data/lib/rspec/mocks/any_instance/recorder.rb +23 -31
  44. data/lib/rspec/mocks/any_instance/stub_chain.rb +9 -4
  45. data/lib/rspec/mocks/argument_list_matcher.rb +8 -1
  46. data/lib/rspec/mocks/argument_matchers.rb +26 -12
  47. data/lib/rspec/mocks/arity_calculator.rb +66 -0
  48. data/lib/rspec/mocks/configuration.rb +42 -14
  49. data/lib/rspec/mocks/error_generator.rb +34 -10
  50. data/lib/rspec/mocks/example_methods.rb +64 -19
  51. data/lib/rspec/mocks/extensions/marshal.rb +0 -15
  52. data/lib/rspec/mocks/framework.rb +4 -4
  53. data/lib/rspec/mocks/instance_method_stasher.rb +80 -62
  54. data/lib/rspec/mocks/matchers/have_received.rb +18 -14
  55. data/lib/rspec/mocks/matchers/receive.rb +29 -7
  56. data/lib/rspec/mocks/matchers/receive_messages.rb +72 -0
  57. data/lib/rspec/mocks/message_expectation.rb +95 -148
  58. data/lib/rspec/mocks/method_double.rb +77 -139
  59. data/lib/rspec/mocks/method_reference.rb +95 -0
  60. data/lib/rspec/mocks/mock.rb +1 -1
  61. data/lib/rspec/mocks/mutate_const.rb +12 -9
  62. data/lib/rspec/mocks/object_reference.rb +90 -0
  63. data/lib/rspec/mocks/order_group.rb +49 -7
  64. data/lib/rspec/mocks/proxy.rb +72 -33
  65. data/lib/rspec/mocks/proxy_for_nil.rb +2 -2
  66. data/lib/rspec/mocks/space.rb +13 -18
  67. data/lib/rspec/mocks/stub_chain.rb +2 -2
  68. data/lib/rspec/mocks/syntax.rb +61 -36
  69. data/lib/rspec/mocks/targets.rb +40 -19
  70. data/lib/rspec/mocks/test_double.rb +12 -56
  71. data/lib/rspec/mocks/verifying_double.rb +77 -0
  72. data/lib/rspec/mocks/verifying_message_expecation.rb +60 -0
  73. data/lib/rspec/mocks/verifying_proxy.rb +151 -0
  74. data/lib/rspec/mocks/version.rb +1 -1
  75. data/spec/rspec/mocks/and_call_original_spec.rb +34 -30
  76. data/spec/rspec/mocks/and_yield_spec.rb +2 -2
  77. data/spec/rspec/mocks/any_instance/message_chains_spec.rb +1 -1
  78. data/spec/rspec/mocks/any_instance_spec.rb +53 -260
  79. data/spec/rspec/mocks/argument_expectation_spec.rb +4 -4
  80. data/spec/rspec/mocks/arity_calculator_spec.rb +95 -0
  81. data/spec/rspec/mocks/array_including_matcher_spec.rb +41 -0
  82. data/spec/rspec/mocks/at_least_spec.rb +4 -32
  83. data/spec/rspec/mocks/block_return_value_spec.rb +4 -135
  84. data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +10 -11
  85. data/spec/rspec/mocks/configuration_spec.rb +79 -0
  86. data/spec/rspec/mocks/double_spec.rb +10 -78
  87. data/spec/rspec/mocks/extensions/marshal_spec.rb +0 -8
  88. data/spec/rspec/mocks/failing_argument_matchers_spec.rb +49 -4
  89. data/spec/rspec/mocks/instance_method_stasher_spec.rb +20 -3
  90. data/spec/rspec/mocks/matchers/have_received_spec.rb +74 -0
  91. data/spec/rspec/mocks/matchers/receive_messages_spec.rb +140 -0
  92. data/spec/rspec/mocks/matchers/receive_spec.rb +82 -42
  93. data/spec/rspec/mocks/methods_spec.rb +1 -1
  94. data/spec/rspec/mocks/{bug_report_830_spec.rb → mock_expectation_error_spec.rb} +4 -3
  95. data/spec/rspec/mocks/mock_ordering_spec.rb +11 -0
  96. data/spec/rspec/mocks/mock_space_spec.rb +10 -1
  97. data/spec/rspec/mocks/mock_spec.rb +26 -82
  98. data/spec/rspec/mocks/multiple_return_value_spec.rb +1 -1
  99. data/spec/rspec/mocks/mutate_const_spec.rb +18 -5
  100. data/spec/rspec/mocks/null_object_mock_spec.rb +6 -4
  101. data/spec/rspec/mocks/options_hash_spec.rb +3 -3
  102. data/spec/rspec/mocks/order_group_spec.rb +27 -0
  103. data/spec/rspec/mocks/partial_mock_spec.rb +101 -1
  104. data/spec/rspec/mocks/passing_argument_matchers_spec.rb +3 -20
  105. data/spec/rspec/mocks/record_messages_spec.rb +4 -4
  106. data/spec/rspec/mocks/serialization_spec.rb +4 -6
  107. data/spec/rspec/mocks/space_spec.rb +3 -3
  108. data/spec/rspec/mocks/stub_chain_spec.rb +0 -12
  109. data/spec/rspec/mocks/stub_spec.rb +23 -44
  110. data/spec/rspec/mocks/test_double_spec.rb +3 -22
  111. data/spec/rspec/mocks/verifying_double_spec.rb +327 -0
  112. data/spec/rspec/mocks/verifying_message_expecation_spec.rb +68 -0
  113. data/spec/rspec/mocks_spec.rb +16 -39
  114. data/spec/spec_helper.rb +29 -18
  115. metadata +131 -86
  116. metadata.gz.sig +1 -0
  117. data/features/message_expectations/expect_any_instance_of.feature +0 -27
  118. data/lib/rspec/mocks/caller_filter.rb +0 -60
  119. data/lib/rspec/mocks/deprecation.rb +0 -26
  120. data/lib/rspec/mocks/extensions/instance_exec.rb +0 -34
  121. data/lib/rspec/mocks/extensions/proc.rb +0 -63
  122. data/lib/spec/mocks.rb +0 -4
  123. data/spec/rspec/mocks/and_return_spec.rb +0 -17
  124. data/spec/rspec/mocks/any_number_of_times_spec.rb +0 -36
  125. data/spec/rspec/mocks/before_all_spec.rb +0 -74
  126. data/spec/rspec/mocks/bug_report_10260_spec.rb +0 -8
  127. data/spec/rspec/mocks/bug_report_10263_spec.rb +0 -27
  128. data/spec/rspec/mocks/bug_report_11545_spec.rb +0 -32
  129. data/spec/rspec/mocks/bug_report_496_spec.rb +0 -17
  130. data/spec/rspec/mocks/bug_report_600_spec.rb +0 -22
  131. data/spec/rspec/mocks/bug_report_7611_spec.rb +0 -16
  132. data/spec/rspec/mocks/bug_report_8165_spec.rb +0 -31
  133. data/spec/rspec/mocks/bug_report_957_spec.rb +0 -22
@@ -19,7 +19,7 @@ module RSpec
19
19
  chain.shift
20
20
  matching_stub.invoke(nil).stub_chain(*chain, &block)
21
21
  else
22
- next_in_chain = Double.new
22
+ next_in_chain = Mock.new
23
23
  object.stub(chain.shift) { next_in_chain }
24
24
  StubChain.stub_chain_on(next_in_chain, *chain, &block)
25
25
  end
@@ -35,7 +35,7 @@ module RSpec
35
35
  hash = chain.pop
36
36
  hash.each do |k,v|
37
37
  chain << k
38
- blk = Proc.new { v }
38
+ blk = lambda { v }
39
39
  end
40
40
  end
41
41
  return chain.join('.').split('.'), blk
@@ -5,75 +5,81 @@ module RSpec
5
5
  # provided by rspec-mocks.
6
6
  module Syntax
7
7
  # @api private
8
- #
9
- # Common stubbing logic for both `stub` and `stub!`. This used to
10
- # live in `stub`, and `stub!` delegated to `stub`, but we discovered
11
- # that `stub!` was delegating to `RSpec::Mocks::ExampleMethods#stub`
12
- # (which declares a test double) when called with an implicit receiver,
13
- # which was a regression in 2.14.0.
14
- def self.stub_object(object, message_or_hash, opts = {}, &block)
15
- if ::Hash === message_or_hash
16
- message_or_hash.each {|message, value| stub_object(object, message).and_return value }
17
- else
18
- opts[:expected_from] = CallerFilter.first_non_rspec_line
19
- ::RSpec::Mocks.allow_message(object, message_or_hash, opts, &block)
8
+ def self.warn_about_should!
9
+ @warn_about_should = true
10
+ end
11
+
12
+ # @api private
13
+ def self.warn_unless_should_configured(method_name)
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 => "the new `:expect` syntax or explicitly enable `:should`"
18
+ )
19
+
20
+ @warn_about_should = false
20
21
  end
21
22
  end
22
23
 
23
24
  # @api private
24
25
  # Enables the should syntax (`dbl.stub`, `dbl.should_receive`, etc).
25
26
  def self.enable_should(syntax_host = default_should_syntax_host)
27
+ @warn_about_should = false
26
28
  return if should_enabled?(syntax_host)
27
29
 
28
- syntax_host.class_eval do
30
+ syntax_host.class_exec do
29
31
  def should_receive(message, opts={}, &block)
32
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
30
33
  opts[:expected_from] ||= CallerFilter.first_non_rspec_line
31
- ::RSpec::Mocks.expect_message(self, message.to_sym, opts, &block)
34
+ ::RSpec::Mocks.expect_message(self, message, opts, &block)
32
35
  end
33
36
 
34
37
  def should_not_receive(message, &block)
35
- opts = { :expected_from => CallerFilter.first_non_rspec_line }
36
- ::RSpec::Mocks.expect_message(self, message.to_sym, opts, &block).never
38
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
39
+ opts = {:expected_from => CallerFilter.first_non_rspec_line}
40
+ ::RSpec::Mocks.expect_message(self, message, opts, &block).never
37
41
  end
38
42
 
39
43
  def stub(message_or_hash, opts={}, &block)
40
- ::RSpec::Mocks::Syntax.stub_object(self, message_or_hash, opts, &block)
44
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
45
+ if ::Hash === message_or_hash
46
+ message_or_hash.each {|message, value| stub(message).and_return value }
47
+ else
48
+ opts[:expected_from] = CallerFilter.first_non_rspec_line
49
+ ::RSpec::Mocks.allow_message(self, message_or_hash, opts, &block)
50
+ end
41
51
  end
42
52
 
43
53
  def unstub(message)
54
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
44
55
  ::RSpec::Mocks.space.proxy_for(self).remove_stub(message)
45
56
  end
46
57
 
47
- def stub!(message_or_hash, opts={}, &block)
48
- ::RSpec.deprecate "stub!", :replacement => "stub"
49
- ::RSpec::Mocks::Syntax.stub_object(self, message_or_hash, opts, &block)
50
- end
51
-
52
- def unstub!(message)
53
- ::RSpec.deprecate "unstub!", :replacement => "unstub"
54
- unstub(message)
55
- end
56
-
57
58
  def stub_chain(*chain, &blk)
59
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
58
60
  ::RSpec::Mocks::StubChain.stub_chain_on(self, *chain, &blk)
59
61
  end
60
62
 
61
63
  def as_null_object
64
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
62
65
  @_null_object = true
63
66
  ::RSpec::Mocks.proxy_for(self).as_null_object
64
67
  end
65
68
 
66
69
  def null_object?
70
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
67
71
  defined?(@_null_object)
68
72
  end
69
73
 
70
74
  def received_message?(message, *args, &block)
75
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
71
76
  ::RSpec::Mocks.proxy_for(self).received_message?(message, *args, &block)
72
77
  end
73
78
 
74
79
  unless Class.respond_to? :any_instance
75
- Class.class_eval do
80
+ Class.class_exec do
76
81
  def any_instance
82
+ ::RSpec::Mocks::Syntax.warn_unless_should_configured(__method__)
77
83
  ::RSpec::Mocks.any_instance_recorder_for(self)
78
84
  end
79
85
  end
@@ -86,20 +92,18 @@ module RSpec
86
92
  def self.disable_should(syntax_host = default_should_syntax_host)
87
93
  return unless should_enabled?(syntax_host)
88
94
 
89
- syntax_host.class_eval do
95
+ syntax_host.class_exec do
90
96
  undef should_receive
91
97
  undef should_not_receive
92
98
  undef stub
93
99
  undef unstub
94
- undef stub!
95
- undef unstub!
96
100
  undef stub_chain
97
101
  undef as_null_object
98
102
  undef null_object?
99
103
  undef received_message?
100
104
  end
101
105
 
102
- Class.class_eval do
106
+ Class.class_exec do
103
107
  undef any_instance
104
108
  end
105
109
  end
@@ -109,11 +113,17 @@ module RSpec
109
113
  def self.enable_expect(syntax_host = ::RSpec::Mocks::ExampleMethods)
110
114
  return if expect_enabled?(syntax_host)
111
115
 
112
- syntax_host.class_eval do
116
+ syntax_host.class_exec do
113
117
  def receive(method_name, &block)
114
118
  Matchers::Receive.new(method_name, block)
115
119
  end
116
120
 
121
+ def receive_messages(message_return_value_hash)
122
+ matcher = Matchers::ReceiveMessages.new(message_return_value_hash)
123
+ matcher.warn_about_block if block_given?
124
+ matcher
125
+ end
126
+
117
127
  def allow(target)
118
128
  AllowanceTarget.new(target)
119
129
  end
@@ -127,7 +137,7 @@ module RSpec
127
137
  end
128
138
  end
129
139
 
130
- RSpec::Mocks::ExampleMethods::ExpectHost.class_eval do
140
+ RSpec::Mocks::ExampleMethods::ExpectHost.class_exec do
131
141
  def expect(target)
132
142
  ExpectationTarget.new(target)
133
143
  end
@@ -139,14 +149,15 @@ module RSpec
139
149
  def self.disable_expect(syntax_host = ::RSpec::Mocks::ExampleMethods)
140
150
  return unless expect_enabled?(syntax_host)
141
151
 
142
- syntax_host.class_eval do
152
+ syntax_host.class_exec do
143
153
  undef receive
154
+ undef receive_messages
144
155
  undef allow
145
156
  undef expect_any_instance_of
146
157
  undef allow_any_instance_of
147
158
  end
148
159
 
149
- RSpec::Mocks::ExampleMethods::ExpectHost.class_eval do
160
+ RSpec::Mocks::ExampleMethods::ExpectHost.class_exec do
150
161
  undef expect
151
162
  end
152
163
  end
@@ -343,6 +354,20 @@ module RSpec
343
354
  # expect(obj).to receive(:hello).with("world").exactly(3).times
344
355
  #
345
356
  # @note This is only available when you have enabled the `expect` syntax.
357
+ #
358
+ # @method receive_messages
359
+ # Shorthand syntax used to setup message(s), and their return value(s),
360
+ # that you expect or allow an object to receive. The method takes a hash
361
+ # of messages and their respective return values. Unlike with `receive`,
362
+ # you cannot apply further customizations using a block or the fluent
363
+ # interface.
364
+ #
365
+ # @example
366
+ #
367
+ # allow(obj).to receive_messages(:speak => "Hello World")
368
+ # allow(obj).to receive_messages(:speak => "Hello", :meow => "Meow")
369
+ #
370
+ # @note This is only available when you have enabled the `expect` syntax.
346
371
  end
347
372
  end
348
373
  end
@@ -8,30 +8,51 @@ module RSpec
8
8
  @target = target
9
9
  end
10
10
 
11
- def self.delegate_to(matcher_method, options = {})
12
- method_name = options.fetch(:from) { :to }
13
- class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
14
- def #{method_name}(matcher, &block)
15
- unless Matchers::Receive === matcher
16
- raise UnsupportedMatcherError, "only the `receive` matcher is supported " +
17
- "with `\#{expression}(...).\#{#{method_name.inspect}}`, but you have provided: \#{matcher}"
11
+ def self.delegate_to(matcher_method)
12
+ define_method(:to) do |matcher, &block|
13
+ unless Matchers::Receive === matcher || Matchers::ReceiveMessages === matcher
14
+ raise_unsupported_matcher(:to, matcher)
18
15
  end
16
+ define_matcher(matcher, matcher_method, &block)
17
+ end
18
+ end
19
19
 
20
- matcher.__send__(#{matcher_method.inspect}, @target, &block)
20
+ def self.delegate_not_to(matcher_method, options = {})
21
+ method_name = options.fetch(:from)
22
+ define_method(method_name) do |matcher, &block|
23
+ case matcher
24
+ when Matchers::Receive then define_matcher(matcher, matcher_method, &block)
25
+ when Matchers::ReceiveMessages then raise_negation_unsupported(method_name, matcher)
26
+ else
27
+ raise_unsupported_matcher(method_name, matcher)
28
+ end
21
29
  end
22
- RUBY
23
30
  end
24
31
 
25
- def self.disallow_negation(method)
26
- define_method method do |*args|
27
- raise NegationUnsupportedError,
28
- "`#{expression}(...).#{method} receive` is not supported since it " +
29
- "doesn't really make sense. What would it even mean?"
32
+ def self.disallow_negation(method_name)
33
+ define_method(method_name) do |matcher, *args|
34
+ raise_negation_unsupported(method_name, matcher)
30
35
  end
31
36
  end
32
37
 
33
38
  private
34
39
 
40
+ def define_matcher(matcher, name, &block)
41
+ matcher.__send__(name, @target, &block)
42
+ end
43
+
44
+ def raise_unsupported_matcher(method_name, matcher)
45
+ raise UnsupportedMatcherError,
46
+ "only the `receive` or `receive_messages` matchers are supported " +
47
+ "with `#{expression}(...).#{method_name}`, but you have provided: #{matcher}"
48
+ end
49
+
50
+ def raise_negation_unsupported(method_name, matcher)
51
+ raise NegationUnsupportedError,
52
+ "`#{expression}(...).#{method_name} #{matcher.name}` is not supported since it " +
53
+ "doesn't really make sense. What would it even mean?"
54
+ end
55
+
35
56
  def expression
36
57
  self.class::EXPRESSION
37
58
  end
@@ -47,12 +68,12 @@ module RSpec
47
68
  class ExpectationTarget < TargetBase
48
69
  EXPRESSION = :expect
49
70
  delegate_to :setup_expectation
50
- delegate_to :setup_negative_expectation, :from => :not_to
51
- delegate_to :setup_negative_expectation, :from => :to_not
71
+ delegate_not_to :setup_negative_expectation, :from => :not_to
72
+ delegate_not_to :setup_negative_expectation, :from => :to_not
52
73
  end
53
74
 
54
75
  class AnyInstanceAllowanceTarget < TargetBase
55
- EXPRESSION = :expect_any_instance_of
76
+ EXPRESSION = :allow_any_instance_of
56
77
  delegate_to :setup_any_instance_allowance
57
78
  disallow_negation :not_to
58
79
  disallow_negation :to_not
@@ -61,8 +82,8 @@ module RSpec
61
82
  class AnyInstanceExpectationTarget < TargetBase
62
83
  EXPRESSION = :expect_any_instance_of
63
84
  delegate_to :setup_any_instance_expectation
64
- delegate_to :setup_any_instance_negative_expectation, :from => :not_to
65
- delegate_to :setup_any_instance_negative_expectation, :from => :to_not
85
+ delegate_not_to :setup_any_instance_negative_expectation, :from => :not_to
86
+ delegate_not_to :setup_any_instance_negative_expectation, :from => :to_not
66
87
  end
67
88
  end
68
89
  end
@@ -12,16 +12,15 @@ module RSpec
12
12
  # module = Module.new
13
13
  # RSpec::Mocks::TestDouble.extend_onto(module, "MyMixin", :foo => "bar")
14
14
  # module.foo #=> "bar"
15
- def self.extend_onto(object, name=nil, stubs_and_options={})
16
- RSpec.deprecate("`RSpec::Mocks::TestDouble.extend_onto(...)`")
15
+ def self.extend_onto(object, name=nil, stubs={})
17
16
  object.extend self
18
- object.send(:__initialize_as_test_double, name, stubs_and_options)
17
+ object.send(:__initialize_as_test_double, name, stubs)
19
18
  end
20
19
 
21
20
  # Creates a new test double with a `name` (that will be used in error
22
21
  # messages only)
23
- def initialize(name=nil, stubs_and_options={})
24
- __initialize_as_test_double(name, stubs_and_options)
22
+ def initialize(name=nil, stubs={})
23
+ __initialize_as_test_double(name, stubs)
25
24
  end
26
25
 
27
26
  # Tells the object to respond to all messages. If specific stub values
@@ -29,14 +28,11 @@ module RSpec
29
28
  # returned.
30
29
  def as_null_object
31
30
  __mock_proxy.as_null_object
32
- @__null_object = true
33
- self
34
31
  end
35
32
 
36
33
  # Returns true if this object has received `as_null_object`
37
34
  def null_object?
38
- __warn_of_expired_use_if_expired
39
- @__null_object
35
+ __mock_proxy.null_object?
40
36
  end
41
37
 
42
38
  # This allows for comparing the mock to other objects that proxy such as
@@ -64,37 +60,21 @@ module RSpec
64
60
  __mock_proxy.null_object? ? true : super
65
61
  end
66
62
 
67
- def freeze
68
- RSpec.deprecate 'Freezing a test double'
69
- super
70
- end
71
-
72
63
  # @private
73
- def __build_mock_proxy
74
- proxy = TestDoubleProxy.new(self, @name, @options || {})
75
- __warn_of_expired_use_if_expired
76
- proxy.as_null_object if @__null_object
77
- proxy
78
- end
79
-
80
- def __warn_if_used_further!
81
- @__unfrozen_attributes[:expired] = true
64
+ def __build_mock_proxy(order_group)
65
+ Proxy.new(self, order_group, @name)
82
66
  end
83
67
 
84
68
  private
85
69
 
86
- def __initialize_as_test_double(name=nil, stubs_and_options={})
87
- @__null_object = false
88
- @__unfrozen_attributes = {}
89
-
90
- if name.is_a?(Hash) && stubs_and_options.empty?
91
- stubs_and_options = name
70
+ def __initialize_as_test_double(name=nil, stubs={})
71
+ if Hash === name && stubs.empty?
72
+ stubs = name
92
73
  @name = nil
93
74
  else
94
75
  @name = name
95
76
  end
96
- @options = extract_options(stubs_and_options)
97
- assign_stubs(stubs_and_options)
77
+ assign_stubs(stubs)
98
78
  end
99
79
 
100
80
  def method_missing(message, *args, &block)
@@ -115,33 +95,9 @@ module RSpec
115
95
  end
116
96
  end
117
97
 
118
- def extract_options(stubs_and_options)
119
- if stubs_and_options[:null_object]
120
- @null_object = stubs_and_options.delete(:null_object)
121
- RSpec.deprecate("double('name', :null_object => true)", :replacement => "double('name').as_null_object")
122
- end
123
- options = {}
124
- extract_option(stubs_and_options, options, :__declared_as, 'Mock')
125
- options
126
- end
127
-
128
- def extract_option(source, target, key, default=nil)
129
- if source[key]
130
- target[key] = source.delete(key)
131
- elsif default
132
- target[key] = default
133
- end
134
- end
135
-
136
98
  def assign_stubs(stubs)
137
99
  stubs.each_pair do |message, response|
138
- Mocks.allow_message(self, message).and_return(response)
139
- end
140
- end
141
-
142
- def __warn_of_expired_use_if_expired
143
- if @__unfrozen_attributes && @__unfrozen_attributes[:expired]
144
- RSpec.deprecate "Continuing to use a test double after it has been reset (e.g. in a subsequent example)"
100
+ __mock_proxy.add_simple_stub(message, response)
145
101
  end
146
102
  end
147
103
 
@@ -0,0 +1,77 @@
1
+ require 'rspec/mocks/mock'
2
+ require 'rspec/mocks/verifying_proxy'
3
+
4
+ module RSpec
5
+ module Mocks
6
+
7
+ module VerifyingDouble
8
+ def method_missing(message, *args, &block)
9
+ # Null object conditional is an optimization. If not a null object,
10
+ # validity of method expectations will have been checked at definition
11
+ # time.
12
+ __mock_proxy.ensure_implemented(message) if null_object?
13
+ super
14
+ end
15
+ end
16
+
17
+ # A mock providing a custom proxy that can verify the validity of any
18
+ # method stubs or expectations against the public instance methods of the
19
+ # given class.
20
+ class InstanceVerifyingDouble
21
+ include TestDouble
22
+ include VerifyingDouble
23
+
24
+ def initialize(doubled_module, *args)
25
+ @doubled_module = doubled_module
26
+
27
+ __initialize_as_test_double(doubled_module, *args)
28
+ end
29
+
30
+ def __build_mock_proxy(order_group)
31
+ VerifyingProxy.new(self, order_group,
32
+ @doubled_module,
33
+ InstanceMethodReference
34
+ )
35
+ end
36
+ end
37
+
38
+ # An awkward module necessary because we cannot otherwise have
39
+ # ClassVerifyingDouble inherit from Module and still share these methods.
40
+ module ObjectVerifyingDoubleMethods
41
+ include TestDouble
42
+ include VerifyingDouble
43
+
44
+ def initialize(doubled_module, *args)
45
+ @doubled_module = doubled_module
46
+
47
+ __initialize_as_test_double(doubled_module, *args)
48
+ end
49
+
50
+ def __build_mock_proxy(order_group)
51
+ VerifyingProxy.new(self, order_group,
52
+ @doubled_module,
53
+ ObjectMethodReference
54
+ )
55
+ end
56
+
57
+ def as_stubbed_const(options = {})
58
+ ConstantMutator.stub(@doubled_module.const_to_replace, self, options)
59
+ self
60
+ end
61
+ end
62
+
63
+ # Similar to an InstanceVerifyingDouble, except that it verifies against
64
+ # public methods of the given object.
65
+ class ObjectVerifyingDouble
66
+ include ObjectVerifyingDoubleMethods
67
+ end
68
+
69
+ # Effectively the same as an ObjectVerifyingDouble (since a class is a type
70
+ # of object), except with Module in the inheritance chain so that
71
+ # transferring nested constants to work.
72
+ class ClassVerifyingDouble < Module
73
+ include ObjectVerifyingDoubleMethods
74
+ end
75
+
76
+ end
77
+ end