rspec-mocks 2.99.4 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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