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
@@ -12,11 +12,16 @@ module RSpec
12
12
  private
13
13
 
14
14
  def create_message_expectation_on(instance)
15
- super do |proxy, expected_from|
16
- stub = proxy.add_stub(expected_from, *@expectation_args, &@expectation_block)
17
- @recorder.stubs[stub.message] << stub
18
- stub
15
+ proxy = ::RSpec::Mocks.proxy_for(instance)
16
+ expected_from = IGNORED_BACKTRACE_LINE
17
+ stub = proxy.add_stub(expected_from, *@expectation_args, &@expectation_block)
18
+ @recorder.stubs[stub.message] << stub
19
+
20
+ if RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks?
21
+ stub.and_yield_receiver_to_implementation
19
22
  end
23
+
24
+ stub
20
25
  end
21
26
 
22
27
  def invocation_order
@@ -23,6 +23,8 @@ module RSpec
23
23
  # arg_list_matcher = RSpec::Mocks::ArgumentListMatcher.new(123, hash_including(:a => 'b'))
24
24
  # arg_list_matcher.args_match?(123, :a => 'b')
25
25
  #
26
+ # This class is immutable.
27
+ #
26
28
  # @see ArgumentMatchers
27
29
  class ArgumentListMatcher
28
30
  # @private
@@ -69,7 +71,7 @@ module RSpec
69
71
 
70
72
  def matcher_for(arg)
71
73
  return ArgumentMatchers::MatcherMatcher.new(arg) if is_matcher?(arg)
72
- return ArgumentMatchers::RegexpMatcher.new(arg) if arg.is_a?(Regexp)
74
+ return ArgumentMatchers::RegexpMatcher.new(arg) if Regexp === arg
73
75
  return ArgumentMatchers::EqualityProxy.new(arg)
74
76
  end
75
77
 
@@ -92,6 +94,11 @@ module RSpec
92
94
  def match_any_args?
93
95
  @match_any_args
94
96
  end
97
+
98
+ # Value that will match all argument lists.
99
+ #
100
+ # @private
101
+ MATCH_ALL = new(ArgumentMatchers::AnyArgsMatcher.new)
95
102
  end
96
103
  end
97
104
  end
@@ -83,6 +83,20 @@ module RSpec
83
83
  end
84
84
  end
85
85
 
86
+ class ArrayIncludingMatcher
87
+ def initialize(expected)
88
+ @expected = expected
89
+ end
90
+
91
+ def ==(actual)
92
+ Set.new(actual).superset?(Set.new(@expected))
93
+ end
94
+
95
+ def description
96
+ "array_including(#{@expected.join(",")})"
97
+ end
98
+ end
99
+
86
100
  class DuckTypeMatcher
87
101
  def initialize(*methods_to_respond_to)
88
102
  @methods_to_respond_to = methods_to_respond_to
@@ -109,18 +123,6 @@ module RSpec
109
123
  end
110
124
 
111
125
  def ==(expected)
112
- if defined?(DateTime) && DateTime === expected
113
- RSpec.warn_deprecation <<-WARN.gsub(/^\s*\|/,'')
114
- |In RSpec 3.0.0 matchers use `#===` (the match operator) to perform
115
- |comparision between expected and actual arguments. Due to strange
116
- |behaviour with `DateTime#===` (which ignores the time of the object
117
- |when performing a comparison) this may result in undesired
118
- |behaviour. We recommend you switch to a `Date` or `Time` object
119
- |instead.
120
- |
121
- |Called from: #{RSpec::CallerFilter.first_non_rspec_line}
122
- WARN
123
- end
124
126
  @given == expected
125
127
  end
126
128
  end
@@ -204,6 +206,18 @@ module RSpec
204
206
  HashIncludingMatcher.new(anythingize_lonely_keys(*args))
205
207
  end
206
208
 
209
+ # Matches an array that includes the specified items at least once.
210
+ # Ignores duplicates and additional values
211
+ #
212
+ # @example
213
+ #
214
+ # object.should_receive(:message).with(array_including(1,2,3))
215
+ # object.should_receive(:message).with(array_including([1,2,3]))
216
+ def array_including(*args)
217
+ actually_an_array = Array === args.first && args.count == 1 ? args.first : args
218
+ ArrayIncludingMatcher.new(actually_an_array)
219
+ end
220
+
207
221
  # Matches a hash that doesn't include the specified key(s) or key/value.
208
222
  #
209
223
  # @example
@@ -0,0 +1,66 @@
1
+ module RSpec
2
+ module Mocks
3
+
4
+ # Figures out the valid arity range for a method. Surprisingly non-trivial.
5
+ class ArityCalculator
6
+
7
+ def initialize(method)
8
+ @method = method
9
+ end
10
+
11
+ # @api private
12
+ def within_range?(actual)
13
+ min_arity <= actual && actual <= max_arity
14
+ end
15
+
16
+ # @api private
17
+ def range_description
18
+ return min_arity.to_s if min_arity == max_arity
19
+ return "#{min_arity} or more" if max_arity == INFINITY
20
+ "#{min_arity} to #{max_arity}"
21
+ end
22
+
23
+ private
24
+
25
+ def method
26
+ @method
27
+ end
28
+
29
+ # @api private
30
+ def self.supports_optional_and_splat_args?
31
+ Method.method_defined?(:parameters)
32
+ end
33
+
34
+ def min_arity
35
+ return method.arity if method.arity >= 0
36
+ # `~` inverts the one's complement and gives us the number of
37
+ # required arguments.
38
+ ~method.arity
39
+ end
40
+
41
+ if supports_optional_and_splat_args?
42
+ def max_arity
43
+ params = method.parameters
44
+ if params.any? {|(type, _)| type == :rest }
45
+ # Method takes a splat argument
46
+ return INFINITY
47
+ else
48
+ params.count {|(type, _)| type != :block }
49
+ end
50
+ end
51
+ else
52
+ def max_arity
53
+ # On 1.8, Method#parameters does not exist. There is no way to
54
+ # distinguish between default and splat args, so there is no way to
55
+ # have it work correctly for both default and splat args, as far as I
56
+ # can tell. The best we can do is consider it INFINITY (to be
57
+ # tolerant of splat args).
58
+ method.arity < 0 ? INFINITY : method.arity
59
+ end
60
+ end
61
+
62
+ INFINITY = 1/0.0
63
+ end
64
+ end
65
+ end
66
+
@@ -4,9 +4,10 @@ module RSpec
4
4
  class Configuration
5
5
 
6
6
  def initialize
7
- @yield_receiver_to_any_instance_implementation_blocks = false
8
- @should_warn_about_any_instance_blocks = true
9
- @marshal_patched = false
7
+ @yield_receiver_to_any_instance_implementation_blocks = true
8
+ @verify_doubled_constant_names = false
9
+ @transfer_nested_constants = false
10
+ @verify_partial_doubles = false
10
11
  end
11
12
 
12
13
  def yield_receiver_to_any_instance_implementation_blocks?
@@ -14,14 +15,9 @@ module RSpec
14
15
  end
15
16
 
16
17
  def yield_receiver_to_any_instance_implementation_blocks=(arg)
17
- @should_warn_about_any_instance_blocks = false
18
18
  @yield_receiver_to_any_instance_implementation_blocks = arg
19
19
  end
20
20
 
21
- def should_warn_about_any_instance_blocks?
22
- @should_warn_about_any_instance_blocks
23
- end
24
-
25
21
  # Adds `stub` and `should_receive` to the given
26
22
  # modules or classes. This is usually only necessary
27
23
  # if you application uses some proxy classes that
@@ -64,12 +60,45 @@ module RSpec
64
60
  syntaxes
65
61
  end
66
62
 
67
- def patch_marshal_to_support_partial_doubles=(val)
68
- @marshal_patched = val
63
+ def verify_doubled_constant_names?
64
+ !!@verify_doubled_constant_names
65
+ end
66
+
67
+ # When this is set to true, an error will be raised when
68
+ # `instance_double` or `class_double` is given the name of an undefined
69
+ # constant. You probably only want to set this when running your entire
70
+ # test suite, with all production code loaded. Setting this for an
71
+ # isolated unit test will prevent you from being able to isolate it!
72
+ def verify_doubled_constant_names=(val)
73
+ @verify_doubled_constant_names = val
69
74
  end
70
75
 
71
- def marshal_patched?
72
- @marshal_patched
76
+ def transfer_nested_constants?
77
+ !!@transfer_nested_constants
78
+ end
79
+
80
+ # Sets the default for the `transfer_nested_constants` option when
81
+ # stubbing constants.
82
+ def transfer_nested_constants=(val)
83
+ @transfer_nested_constants = val
84
+ end
85
+
86
+ # When set to true, partial mocks will be verified the same as object
87
+ # doubles. Any stubs will have their arity checked against the original
88
+ # method, and methods that do not exist cannot be stubbed.
89
+ def verify_partial_doubles=(val)
90
+ @verify_partial_doubles = !!val
91
+ end
92
+
93
+ def verify_partial_doubles?
94
+ @verify_partial_doubles
95
+ end
96
+
97
+ # @api private
98
+ # Resets the configured syntax to the default.
99
+ def reset_syntaxes_to_default
100
+ self.syntax = [:should, :expect]
101
+ RSpec::Mocks::Syntax.warn_about_should!
73
102
  end
74
103
  end
75
104
 
@@ -77,7 +106,6 @@ module RSpec
77
106
  @configuration ||= Configuration.new
78
107
  end
79
108
 
80
- configuration.syntax = [:should, :expect]
109
+ configuration.reset_syntaxes_to_default
81
110
  end
82
111
  end
83
-
@@ -4,8 +4,7 @@ module RSpec
4
4
  class ErrorGenerator
5
5
  attr_writer :opts
6
6
 
7
- def initialize(target, name, options={})
8
- @declared_as = options[:__declared_as] || 'Mock'
7
+ def initialize(target, name)
9
8
  @target = target
10
9
  @name = name
11
10
  end
@@ -48,6 +47,22 @@ module RSpec
48
47
  __raise "(#{intro}).#{message}#{format_args(*args)}\n #{expected_part}\n #{received_part}"
49
48
  end
50
49
 
50
+ # @private
51
+ def raise_unimplemented_error(doubled_module, method_name)
52
+ __raise "%s does not implement:\n %s" % [
53
+ doubled_module.description,
54
+ method_name
55
+ ]
56
+ end
57
+
58
+ # @private
59
+ def raise_arity_error(calculator, actual)
60
+ __raise "Wrong number of arguments. Expected %s, got %s." % [
61
+ calculator.range_description,
62
+ actual
63
+ ]
64
+ end
65
+
51
66
  # @private
52
67
  def received_part_of_expectation_error(actual_received_count, *args)
53
68
  "received: #{count_message(actual_received_count)}" +
@@ -62,11 +77,14 @@ module RSpec
62
77
 
63
78
  # @private
64
79
  def method_call_args_description(args)
65
- if args.first.is_a?(ArgumentMatchers::AnyArgsMatcher)
66
- " with any arguments"
67
- elsif args.first.is_a?(ArgumentMatchers::NoArgsMatcher)
68
- " with no arguments"
69
- elsif args.length > 0
80
+ case args.first
81
+ when ArgumentMatchers::AnyArgsMatcher
82
+ return " with any arguments"
83
+ when ArgumentMatchers::NoArgsMatcher
84
+ return " with no arguments"
85
+ end
86
+
87
+ if args.length > 0
70
88
  " with arguments: #{args.inspect.gsub(/\A\[(.+)\]\z/, '(\1)')}"
71
89
  else
72
90
  ""
@@ -127,9 +145,9 @@ module RSpec
127
145
 
128
146
  def intro
129
147
  if @name
130
- "#{@declared_as} #{@name.inspect}"
148
+ "Double #{@name.inspect}"
131
149
  elsif TestDouble === @target
132
- @declared_as
150
+ "Double"
133
151
  elsif Class === @target
134
152
  "<#{@target.inspect} (class)>"
135
153
  elsif @target
@@ -153,7 +171,13 @@ module RSpec
153
171
  end
154
172
 
155
173
  def arg_list(*args)
156
- args.collect {|arg| arg.respond_to?(:description) ? arg.description : arg.inspect}.join(", ")
174
+ args.collect {|arg| arg_has_valid_description(arg) ? arg.description : arg.inspect }.join(", ")
175
+ end
176
+
177
+ def arg_has_valid_description(arg)
178
+ return false unless arg.respond_to?(:description)
179
+
180
+ !arg.description.nil? && !arg.description.empty?
157
181
  end
158
182
 
159
183
  def format_received_args(*args)
@@ -1,3 +1,5 @@
1
+ require 'rspec/mocks/object_reference'
2
+
1
3
  module RSpec
2
4
  module Mocks
3
5
  module ExampleMethods
@@ -9,12 +11,12 @@ module RSpec
9
11
  # @overload double(name, stubs)
10
12
  # @param name [String/Symbol] (optional) used in
11
13
  # clarify intent
12
- # @param stubs (Hash) (optional) hash of method/return-value pairs
14
+ # @param stubs (Hash) (optional) hash of message/return-value pairs
13
15
  # @return (Mock)
14
16
  #
15
17
  # Constructs an instance of [RSpec::Mocks::Mock](RSpec::Mocks::Mock) configured
16
18
  # with an optional name, used for reporting in failure messages, and an optional
17
- # hash of method/return-value pairs.
19
+ # hash of message/return-value pairs.
18
20
  #
19
21
  # @example
20
22
  #
@@ -25,22 +27,53 @@ module RSpec
25
27
  # card.suit #=> "Spades"
26
28
  # card.rank #=> "A"
27
29
  #
28
- # @see #mock
29
- # @see #stub
30
30
  def double(*args)
31
- declare_double('Double', *args)
31
+ declare_double(Mock, *args)
32
+ end
33
+
34
+ # @overload instance_double(doubled_class)
35
+ # @overload instance_double(doubled_class, stubs)
36
+ # @param doubled_class [String, Class]
37
+ # @param stubs [Hash] (optional) hash of message/return-value pairs
38
+ # @return InstanceVerifyingDouble
39
+ #
40
+ # Constructs a test double against a specific class. If the given class
41
+ # name has been loaded, only instance methods defined on the class are
42
+ # allowed to be stubbed. In all other ways it behaves like a
43
+ # [double](double).
44
+ def instance_double(doubled_class, *args)
45
+ ref = ObjectReference.for(doubled_class)
46
+ declare_verifying_double(InstanceVerifyingDouble, ref, *args)
32
47
  end
33
48
 
34
- # Deprecated: Use [double](#double-instance_method).
35
- def mock(*args)
36
- RSpec.deprecate "mock", :replacement => "double"
37
- declare_double('Mock', *args)
49
+ # @overload class_double(doubled_class)
50
+ # @overload class_double(doubled_class, stubs)
51
+ # @param doubled_class [String, Module]
52
+ # @param stubs [Hash] (optional) hash of message/return-value pairs
53
+ # @return ClassVerifyingDouble
54
+ #
55
+ # Constructs a test double against a specific class. If the given class
56
+ # name has been loaded, only class methods defined on the class are
57
+ # allowed to be stubbed. In all other ways it behaves like a
58
+ # [double](double).
59
+ def class_double(doubled_class, *args)
60
+ ref = ObjectReference.for(doubled_class)
61
+ declare_verifying_double(ClassVerifyingDouble, ref, *args)
38
62
  end
39
63
 
40
- # Deprecated: Use [double](#double-instance_method).
41
- def stub(*args)
42
- RSpec.deprecate "stub", :replacement => "double"
43
- declare_double('Stub', *args)
64
+ # @overload object_double(object_or_name)
65
+ # @overload object_double(object_or_name, stubs)
66
+ # @param object_or_name [String, Object]
67
+ # @param stubs [Hash] (optional) hash of message/return-value pairs
68
+ # @return ObjectVerifyingDouble
69
+ #
70
+ # Constructs a test double against a specific object. Only the methods
71
+ # the object responds to are allowed to be stubbed. If a String argument
72
+ # is provided, it is assumed to reference a constant object which is used
73
+ # for verification. In all other ways it behaves like a [double](double).
74
+ def object_double(object_or_name, *args)
75
+ ref = ObjectReference.for(object_or_name, :allow_direct_object_refs)
76
+ declare_verifying_double(ObjectVerifyingDouble, ref, *args)
44
77
  end
45
78
 
46
79
  # Disables warning messages about expectations being set on nil.
@@ -127,12 +160,12 @@ module RSpec
127
160
  #
128
161
  # # You can also use most message expectations:
129
162
  # expect(invitation).to have_received(:accept).with(mailer).once
130
- def have_received(method_name)
131
- Matchers::HaveReceived.new(method_name)
163
+ def have_received(method_name, &block)
164
+ Matchers::HaveReceived.new(method_name, &block)
132
165
  end
133
166
 
134
167
  def self.included(klass)
135
- klass.class_eval do
168
+ klass.class_exec do
136
169
  # This gets mixed in so that if `RSpec::Matchers` is included in
137
170
  # `klass` later, it's definition of `expect` will take precedence.
138
171
  include ExpectHost unless method_defined?(:expect)
@@ -141,10 +174,22 @@ module RSpec
141
174
 
142
175
  private
143
176
 
144
- def declare_double(declared_as, *args)
177
+ def declare_verifying_double(type, ref, *args)
178
+ if RSpec::Mocks.configuration.verify_doubled_constant_names? &&
179
+ !ref.defined?
180
+
181
+ raise NameError,
182
+ "#{ref.name} is not a defined constant. " +
183
+ "Perhaps you misspelt it? " +
184
+ "Disable check with verify_doubled_constant_names configuration option."
185
+ end
186
+
187
+ declare_double(type, ref, *args)
188
+ end
189
+
190
+ def declare_double(type, *args)
145
191
  args << {} unless Hash === args.last
146
- args.last[:__declared_as] = declared_as
147
- RSpec::Mocks::Double.new(*args)
192
+ type.new(*args)
148
193
  end
149
194
 
150
195
  # This module exists to host the `expect` method for cases where