rspec-mocks 3.0.0.beta2 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Changelog.md +104 -36
  5. data/README.md +35 -4
  6. data/lib/rspec/mocks.rb +52 -13
  7. data/lib/rspec/mocks/any_instance.rb +10 -0
  8. data/lib/rspec/mocks/any_instance/chain.rb +17 -0
  9. data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +1 -1
  10. data/lib/rspec/mocks/any_instance/expectation_chain.rb +9 -6
  11. data/lib/rspec/mocks/any_instance/message_chains.rb +10 -1
  12. data/lib/rspec/mocks/any_instance/proxy.rb +112 -0
  13. data/lib/rspec/mocks/any_instance/recorder.rb +49 -18
  14. data/lib/rspec/mocks/any_instance/stub_chain.rb +5 -3
  15. data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +1 -1
  16. data/lib/rspec/mocks/argument_list_matcher.rb +5 -3
  17. data/lib/rspec/mocks/argument_matchers.rb +28 -12
  18. data/lib/rspec/mocks/configuration.rb +29 -0
  19. data/lib/rspec/mocks/error_generator.rb +2 -5
  20. data/lib/rspec/mocks/example_methods.rb +122 -13
  21. data/lib/rspec/mocks/instance_method_stasher.rb +26 -2
  22. data/lib/rspec/mocks/marshal_extension.rb +41 -0
  23. data/lib/rspec/mocks/matchers/expectation_customization.rb +20 -0
  24. data/lib/rspec/mocks/matchers/receive.rb +6 -20
  25. data/lib/rspec/mocks/matchers/receive_message_chain.rb +7 -5
  26. data/lib/rspec/mocks/matchers/receive_messages.rb +1 -2
  27. data/lib/rspec/mocks/message_chain.rb +9 -9
  28. data/lib/rspec/mocks/message_expectation.rb +6 -5
  29. data/lib/rspec/mocks/method_double.rb +67 -10
  30. data/lib/rspec/mocks/method_reference.rb +1 -1
  31. data/lib/rspec/mocks/mutate_const.rb +10 -14
  32. data/lib/rspec/mocks/object_reference.rb +7 -4
  33. data/lib/rspec/mocks/proxy.rb +95 -8
  34. data/lib/rspec/mocks/space.rb +58 -9
  35. data/lib/rspec/mocks/syntax.rb +128 -210
  36. data/lib/rspec/mocks/targets.rb +6 -8
  37. data/lib/rspec/mocks/test_double.rb +16 -25
  38. data/lib/rspec/mocks/verifying_double.rb +15 -12
  39. data/lib/rspec/mocks/verifying_message_expecation.rb +3 -3
  40. data/lib/rspec/mocks/verifying_proxy.rb +23 -17
  41. data/lib/rspec/mocks/version.rb +3 -1
  42. metadata +29 -257
  43. metadata.gz.sig +0 -0
  44. data/features/README.md +0 -75
  45. data/features/Scope.md +0 -17
  46. data/features/Upgrade.md +0 -22
  47. data/features/argument_matchers/README.md +0 -27
  48. data/features/argument_matchers/explicit.feature +0 -59
  49. data/features/argument_matchers/general_matchers.feature +0 -85
  50. data/features/argument_matchers/type_matchers.feature +0 -26
  51. data/features/message_expectations/README.md +0 -75
  52. data/features/message_expectations/allow_any_instance_of.feature +0 -26
  53. data/features/message_expectations/any_instance.feature +0 -43
  54. data/features/message_expectations/block_local_expectations.feature.pending +0 -55
  55. data/features/message_expectations/call_original.feature +0 -23
  56. data/features/message_expectations/expect_message_using_expect.feature +0 -107
  57. data/features/message_expectations/expect_message_using_should_receive.feature +0 -118
  58. data/features/message_expectations/message_chains_using_expect.feature +0 -49
  59. data/features/message_expectations/receive_counts.feature +0 -209
  60. data/features/message_expectations/warn_when_expectation_is_set_on_nil.feature +0 -50
  61. data/features/method_stubs/README.md +0 -77
  62. data/features/method_stubs/allow_any_instance_of.feature +0 -136
  63. data/features/method_stubs/as_null_object.feature +0 -40
  64. data/features/method_stubs/receive_message_chain.feature +0 -51
  65. data/features/method_stubs/simple_return_value_with_allow.feature +0 -44
  66. data/features/method_stubs/simple_return_value_with_stub.feature +0 -64
  67. data/features/method_stubs/stub_implementation.feature +0 -48
  68. data/features/method_stubs/to_ary.feature +0 -51
  69. data/features/mutating_constants/README.md +0 -82
  70. data/features/mutating_constants/hiding_defined_constant.feature +0 -64
  71. data/features/mutating_constants/stub_defined_constant.feature +0 -78
  72. data/features/mutating_constants/stub_undefined_constant.feature +0 -50
  73. data/features/outside_rspec/standalone.feature +0 -33
  74. data/features/spies/spy_partial_mock_method.feature +0 -34
  75. data/features/spies/spy_pure_mock_method.feature +0 -76
  76. data/features/spies/spy_unstubbed_method.feature +0 -18
  77. data/features/step_definitions/additional_cli_steps.rb +0 -11
  78. data/features/support/env.rb +0 -22
  79. data/features/support/rubinius.rb +0 -6
  80. data/features/test_frameworks/test_unit.feature +0 -54
  81. data/features/verifying_doubles/README.md +0 -17
  82. data/features/verifying_doubles/class_doubles.feature +0 -73
  83. data/features/verifying_doubles/dynamic_classes.feature +0 -71
  84. data/features/verifying_doubles/instance_doubles.feature +0 -103
  85. data/features/verifying_doubles/object_doubles.feature +0 -65
  86. data/features/verifying_doubles/partial_doubles.feature +0 -34
  87. data/lib/rspec/mocks/extensions/marshal.rb +0 -17
  88. data/lib/rspec/mocks/framework.rb +0 -35
  89. data/lib/rspec/mocks/method_signature_verifier.rb +0 -207
  90. data/lib/rspec/mocks/ruby_features.rb +0 -24
  91. data/spec/rspec/mocks/and_call_original_spec.rb +0 -268
  92. data/spec/rspec/mocks/and_return_spec.rb +0 -23
  93. data/spec/rspec/mocks/and_yield_spec.rb +0 -126
  94. data/spec/rspec/mocks/any_instance/message_chains_spec.rb +0 -41
  95. data/spec/rspec/mocks/any_instance_spec.rb +0 -1045
  96. data/spec/rspec/mocks/array_including_matcher_spec.rb +0 -41
  97. data/spec/rspec/mocks/at_least_spec.rb +0 -123
  98. data/spec/rspec/mocks/at_most_spec.rb +0 -90
  99. data/spec/rspec/mocks/before_all_spec.rb +0 -132
  100. data/spec/rspec/mocks/block_return_value_spec.rb +0 -70
  101. data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +0 -204
  102. data/spec/rspec/mocks/configuration_spec.rb +0 -242
  103. data/spec/rspec/mocks/double_spec.rb +0 -874
  104. data/spec/rspec/mocks/example_methods_spec.rb +0 -13
  105. data/spec/rspec/mocks/extensions/marshal_spec.rb +0 -54
  106. data/spec/rspec/mocks/failing_argument_matchers_spec.rb +0 -184
  107. data/spec/rspec/mocks/hash_excluding_matcher_spec.rb +0 -67
  108. data/spec/rspec/mocks/hash_including_matcher_spec.rb +0 -94
  109. data/spec/rspec/mocks/instance_method_stasher_spec.rb +0 -74
  110. data/spec/rspec/mocks/matchers/have_received_spec.rb +0 -347
  111. data/spec/rspec/mocks/matchers/receive_message_chain_spec.rb +0 -198
  112. data/spec/rspec/mocks/matchers/receive_messages_spec.rb +0 -140
  113. data/spec/rspec/mocks/matchers/receive_spec.rb +0 -418
  114. data/spec/rspec/mocks/method_signature_verifier_spec.rb +0 -272
  115. data/spec/rspec/mocks/methods_spec.rb +0 -26
  116. data/spec/rspec/mocks/mock_expectation_error_spec.rb +0 -22
  117. data/spec/rspec/mocks/mock_ordering_spec.rb +0 -114
  118. data/spec/rspec/mocks/multiple_return_value_spec.rb +0 -132
  119. data/spec/rspec/mocks/mutate_const_spec.rb +0 -542
  120. data/spec/rspec/mocks/nil_expectation_warning_spec.rb +0 -52
  121. data/spec/rspec/mocks/null_object_mock_spec.rb +0 -133
  122. data/spec/rspec/mocks/once_counts_spec.rb +0 -52
  123. data/spec/rspec/mocks/options_hash_spec.rb +0 -35
  124. data/spec/rspec/mocks/order_group_spec.rb +0 -27
  125. data/spec/rspec/mocks/partial_double_spec.rb +0 -308
  126. data/spec/rspec/mocks/partial_double_using_mocks_directly_spec.rb +0 -95
  127. data/spec/rspec/mocks/passing_argument_matchers_spec.rb +0 -145
  128. data/spec/rspec/mocks/precise_counts_spec.rb +0 -68
  129. data/spec/rspec/mocks/record_messages_spec.rb +0 -26
  130. data/spec/rspec/mocks/serialization_spec.rb +0 -90
  131. data/spec/rspec/mocks/space_spec.rb +0 -244
  132. data/spec/rspec/mocks/stash_spec.rb +0 -46
  133. data/spec/rspec/mocks/stub_chain_spec.rb +0 -168
  134. data/spec/rspec/mocks/stub_implementation_spec.rb +0 -81
  135. data/spec/rspec/mocks/stub_spec.rb +0 -327
  136. data/spec/rspec/mocks/stubbed_message_expectations_spec.rb +0 -58
  137. data/spec/rspec/mocks/syntax_agnostic_message_matchers_spec.rb +0 -101
  138. data/spec/rspec/mocks/syntax_spec.rb +0 -19
  139. data/spec/rspec/mocks/test_double_spec.rb +0 -49
  140. data/spec/rspec/mocks/to_ary_spec.rb +0 -54
  141. data/spec/rspec/mocks/twice_counts_spec.rb +0 -66
  142. data/spec/rspec/mocks/verifying_double_spec.rb +0 -590
  143. data/spec/rspec/mocks/verifying_message_expecation_spec.rb +0 -69
  144. data/spec/rspec/mocks_spec.rb +0 -192
  145. data/spec/spec_helper.rb +0 -121
@@ -1,65 +0,0 @@
1
- Feature: Using an object double
2
-
3
- `object_double` can be used to create a double from an existing "template"
4
- object, from which it verifies that any stubbed methods on the double also
5
- exist on the template. This is useful for objects that are readily
6
- constructable, but may have far-reaching side-effects such as talking to a
7
- database or external API. In this case, using a double rather than the real
8
- thing allows you to focus on the communication patterns of the object's
9
- interface without having to worry about accidentally causing side-effects.
10
- Object doubles can also be used to verify methods defined on an object using
11
- `method_missing`, which is not possible with `instance_double`.
12
-
13
- In addition, `object_double` can be used with specific constant values, as
14
- shown below. This is for niche situations, such as when dealing with
15
- singleton objects.
16
-
17
- Scenario: doubling an existing object
18
- Given a file named "spec/user_spec.rb" with:
19
- """ruby
20
- class User
21
- # Don't want to accidentally trigger this!
22
- def save; sleep 100; end
23
- end
24
-
25
- def save_user(user)
26
- "saved!" if user.save
27
- end
28
-
29
- describe '#save_user' do
30
- it 'renders message on success' do
31
- user = object_double(User.new, :save => true)
32
- expect(save_user(user)).to eq("saved!")
33
- end
34
- end
35
- """
36
- When I run `rspec spec/user_spec.rb`
37
- Then the examples should all pass
38
-
39
-
40
- Scenario: doubling a constant object
41
- Given a file named "spec/email_spec.rb" with:
42
- """ruby
43
- require 'logger'
44
-
45
- module MyApp
46
- LOGGER = Logger.new("myapp")
47
- end
48
-
49
- class Email
50
- def self.send_to(recipient)
51
- MyApp::LOGGER.info("Sent to #{recipient}")
52
- # other emailing logic
53
- end
54
- end
55
-
56
- describe Email do
57
- it 'logs a message when sending' do
58
- logger = object_double("MyApp::LOGGER", :info => nil).as_stubbed_const
59
- Email.send_to('hello@foo.com')
60
- expect(logger).to have_received(:info).with("Sent to hello@foo.com")
61
- end
62
- end
63
- """
64
- When I run `rspec spec/email_spec.rb`
65
- Then the examples should all pass
@@ -1,34 +0,0 @@
1
- Feature: Partial doubles
2
-
3
- When the `verify_partial_doubles` configuration option is set, the same argument
4
- and method existence checks that are performed for `object_double` are also
5
- performed on partial doubles. You should set this unless you have a good
6
- reason not to. It defaults to off only for backwards compatibility.
7
-
8
- Scenario: doubling an existing object
9
- Given a file named "spec/user_spec.rb" with:
10
- """ruby
11
- class User
12
- def save; false; end
13
- end
14
-
15
- def save_user(user)
16
- "saved!" if user.save
17
- end
18
-
19
- RSpec.configure do |config|
20
- config.mock_with :rspec do |mocks|
21
- mocks.verify_partial_doubles = true
22
- end
23
- end
24
-
25
- describe '#save_user' do
26
- it 'renders message on success' do
27
- user = User.new
28
- expect(user).to receive(:saave).and_return(true) # Typo in name
29
- expect(save_user(user)).to eq("saved!")
30
- end
31
- end
32
- """
33
- When I run `rspec spec/user_spec.rb`
34
- Then the output should contain "1 example, 1 failure"
@@ -1,17 +0,0 @@
1
- module Marshal
2
- class << self
3
- # Duplicates any mock objects before serialization. Otherwise,
4
- # serialization will fail because methods exist on the singleton class.
5
- def dump_with_mocks(object, *rest)
6
- if !::RSpec::Mocks.space.registered?(object) || NilClass === object
7
- dump_without_mocks(object, *rest)
8
- else
9
- dump_without_mocks(object.dup, *rest)
10
- end
11
- end
12
-
13
- alias_method :dump_without_mocks, :dump
14
- undef_method :dump
15
- alias_method :dump, :dump_with_mocks
16
- end
17
- end
@@ -1,35 +0,0 @@
1
- # Require everything except the global extensions of class and object. This
2
- # supports wrapping rspec's mocking functionality without invading every
3
- # object in the system.
4
-
5
- require 'rspec/support/caller_filter'
6
- require 'rspec/support/warnings'
7
- require 'rspec/mocks/instance_method_stasher'
8
- require 'rspec/mocks/method_double'
9
- require 'rspec/mocks/argument_matchers'
10
- require 'rspec/mocks/example_methods'
11
- require 'rspec/mocks/proxy'
12
- require 'rspec/mocks/test_double'
13
- require 'rspec/mocks/argument_list_matcher'
14
- require 'rspec/mocks/message_expectation'
15
- require 'rspec/mocks/order_group'
16
- require 'rspec/mocks/error_generator'
17
- require 'rspec/mocks/space'
18
- require 'rspec/mocks/extensions/marshal'
19
- require 'rspec/mocks/any_instance/chain'
20
- require 'rspec/mocks/any_instance/stub_chain'
21
- require 'rspec/mocks/any_instance/stub_chain_chain'
22
- require 'rspec/mocks/any_instance/expect_chain_chain'
23
- require 'rspec/mocks/any_instance/expectation_chain'
24
- require 'rspec/mocks/any_instance/message_chains'
25
- require 'rspec/mocks/any_instance/recorder'
26
- require 'rspec/mocks/mutate_const'
27
- require 'rspec/mocks/matchers/have_received'
28
- require 'rspec/mocks/matchers/receive'
29
- require 'rspec/mocks/matchers/receive_messages'
30
- require 'rspec/mocks/matchers/receive_message_chain'
31
- require 'rspec/mocks/message_chain'
32
- require 'rspec/mocks/targets'
33
- require 'rspec/mocks/syntax'
34
- require 'rspec/mocks/configuration'
35
- require 'rspec/mocks/verifying_double'
@@ -1,207 +0,0 @@
1
- require 'rspec/mocks/ruby_features'
2
-
3
- module RSpec
4
- module Mocks
5
- # Extracts info about the number of arguments and allowed/required
6
- # keyword args of a given method.
7
- #
8
- # @api private
9
- class MethodSignature
10
- attr_reader :min_non_kw_args, :max_non_kw_args
11
-
12
- def initialize(method)
13
- @method = method
14
- classify_parameters
15
- end
16
-
17
- def non_kw_args_arity_description
18
- case max_non_kw_args
19
- when min_non_kw_args then min_non_kw_args.to_s
20
- when INFINITY then "#{min_non_kw_args} or more"
21
- else "#{min_non_kw_args} to #{max_non_kw_args}"
22
- end
23
- end
24
-
25
- if RubyFeatures.optional_and_splat_args_supported?
26
- def description
27
- @description ||= begin
28
- parts = []
29
-
30
- unless non_kw_args_arity_description == "0"
31
- parts << "arity of #{non_kw_args_arity_description}"
32
- end
33
-
34
- if @optional_kw_args.any?
35
- parts << "optional keyword args (#{@optional_kw_args.map(&:inspect).join(", ")})"
36
- end
37
-
38
- if @required_kw_args.any?
39
- parts << "required keyword args (#{@required_kw_args.map(&:inspect).join(", ")})"
40
- end
41
-
42
- if @allows_any_kw_args
43
- parts << "any additional keyword args"
44
- end
45
-
46
- parts.join(" and ")
47
- end
48
- end
49
-
50
- def missing_kw_args_from(given_kw_args)
51
- @required_kw_args - given_kw_args
52
- end
53
-
54
- def invalid_kw_args_from(given_kw_args)
55
- return [] if @allows_any_kw_args
56
- given_kw_args - @allowed_kw_args
57
- end
58
-
59
- def has_kw_args_in?(args)
60
- return false unless Hash === args.last
61
- return false if args.count <= min_non_kw_args
62
-
63
- @allows_any_kw_args || @allowed_kw_args.any?
64
- end
65
-
66
- def classify_parameters
67
- optional_non_kw_args = @min_non_kw_args = 0
68
- @optional_kw_args, @required_kw_args = [], []
69
- @allows_any_kw_args = false
70
-
71
- @method.parameters.each do |(type, name)|
72
- case type
73
- # def foo(a:)
74
- when :keyreq then @required_kw_args << name
75
- # def foo(a: 1)
76
- when :key then @optional_kw_args << name
77
- # def foo(**kw_args)
78
- when :keyrest then @allows_any_kw_args = true
79
- # def foo(a)
80
- when :req then @min_non_kw_args += 1
81
- # def foo(a = 1)
82
- when :opt then optional_non_kw_args += 1
83
- # def foo(*a)
84
- when :rest then optional_non_kw_args = INFINITY
85
- end
86
- end
87
-
88
- @max_non_kw_args = @min_non_kw_args + optional_non_kw_args
89
- @allowed_kw_args = @required_kw_args + @optional_kw_args
90
- end
91
- else
92
- def description
93
- "arity of #{non_kw_args_arity_description}"
94
- end
95
-
96
- def missing_kw_args_from(given_kw_args)
97
- []
98
- end
99
-
100
- def invalid_kw_args_from(given_kw_args)
101
- []
102
- end
103
-
104
- def has_kw_args_in?(args)
105
- false
106
- end
107
-
108
- def classify_parameters
109
- arity = @method.arity
110
- if arity < 0
111
- # `~` inverts the one's complement and gives us the
112
- # number of required args
113
- @min_non_kw_args = ~arity
114
- @max_non_kw_args = INFINITY
115
- else
116
- @min_non_kw_args = arity
117
- @max_non_kw_args = arity
118
- end
119
- end
120
- end
121
-
122
- INFINITY = 1/0.0
123
- end
124
-
125
- # Deals with the slightly different semantics of block arguments.
126
- # For methods, arguments are required unless a default value is provided.
127
- # For blocks, arguments are optional, even if no default value is provided.
128
- #
129
- # However, we want to treat block args as required since you virtually always
130
- # want to pass a value for each received argument and our `and_yield` has
131
- # treated block args as required for many years.
132
- #
133
- # @api private
134
- class BlockSignature < MethodSignature
135
- if RubyFeatures.optional_and_splat_args_supported?
136
- def classify_parameters
137
- super
138
- @min_non_kw_args = @max_non_kw_args unless @max_non_kw_args == INFINITY
139
- end
140
- end
141
- end
142
-
143
- # Figures out wheter a given method can accept various arguments.
144
- # Surprisingly non-trivial.
145
- #
146
- # @api private
147
- class MethodSignatureVerifier
148
- # @api private
149
- attr_reader :non_kw_args, :kw_args
150
-
151
- def initialize(signature, args)
152
- @signature = signature
153
- @non_kw_args, @kw_args = split_args(*args)
154
- end
155
-
156
- # @api private
157
- def valid?
158
- missing_kw_args.empty? &&
159
- invalid_kw_args.empty? &&
160
- valid_non_kw_args?
161
- end
162
-
163
- # @api private
164
- def error_message
165
- if missing_kw_args.any?
166
- "Missing required keyword arguments: %s" % [
167
- missing_kw_args.join(", ")
168
- ]
169
- elsif invalid_kw_args.any?
170
- "Invalid keyword arguments provided: %s" % [
171
- invalid_kw_args.join(", ")
172
- ]
173
- elsif !valid_non_kw_args?
174
- "Wrong number of arguments. Expected %s, got %s." % [
175
- @signature.non_kw_args_arity_description,
176
- non_kw_args.length
177
- ]
178
- end
179
- end
180
-
181
- private
182
-
183
- def valid_non_kw_args?
184
- actual = non_kw_args.length
185
- @signature.min_non_kw_args <= actual && actual <= @signature.max_non_kw_args
186
- end
187
-
188
- def missing_kw_args
189
- @signature.missing_kw_args_from(kw_args)
190
- end
191
-
192
- def invalid_kw_args
193
- @signature.invalid_kw_args_from(kw_args)
194
- end
195
-
196
- def split_args(*args)
197
- kw_args = if @signature.has_kw_args_in?(args)
198
- args.pop.keys
199
- else
200
- []
201
- end
202
-
203
- [args, kw_args]
204
- end
205
- end
206
- end
207
- end
@@ -1,24 +0,0 @@
1
- module RSpec
2
- module Mocks
3
- # @api private
4
- #
5
- # Provides query methods for ruby features that differ among
6
- # implementations.
7
- module RubyFeatures
8
- def optional_and_splat_args_supported?
9
- Method.method_defined?(:parameters)
10
- end
11
- module_function :optional_and_splat_args_supported?
12
-
13
- def kw_args_supported?
14
- RUBY_VERSION >= '2.0.0' && RUBY_ENGINE != 'rbx'
15
- end
16
- module_function :kw_args_supported?
17
-
18
- def required_kw_args_supported?
19
- RUBY_VERSION >= '2.1.0' && RUBY_ENGINE != 'rbx'
20
- end
21
- module_function :required_kw_args_supported?
22
- end
23
- end
24
- end
@@ -1,268 +0,0 @@
1
- require 'spec_helper'
2
- require 'delegate'
3
-
4
- describe "and_call_original" do
5
- context "on a partial double" do
6
- let(:klass) do
7
- Class.new do
8
- def meth_1
9
- :original
10
- end
11
-
12
- def meth_2(x)
13
- yield x, :additional_yielded_arg
14
- end
15
-
16
- def self.new_instance
17
- new
18
- end
19
- end
20
- end
21
-
22
- let(:instance) { klass.new }
23
-
24
- context "when a method that exists has been stubbed previously" do
25
- before { allow(instance).to receive(:meth_1).and_return(:override) }
26
-
27
- it 'restores the original behavior' do
28
- expect {
29
- allow(instance).to receive(:meth_1).and_call_original
30
- }.to change(instance, :meth_1).from(:override).to(:original)
31
- end
32
- end
33
-
34
- context "when a non-existant method has been stubbed previously" do
35
- it 'restores the original NameError behavior' do
36
- expect { instance.abcd }.to raise_error(NameError).with_message(/abcd/)
37
-
38
- allow(instance).to receive(:abcd).and_return(:override)
39
- expect(instance.abcd).to eq(:override)
40
-
41
- allow(instance).to receive(:abcd).and_call_original
42
- expect { instance.abcd }.to raise_error(NameError).with_message(/abcd/)
43
- end
44
- end
45
-
46
- it 'passes the received message through to the original method' do
47
- expect(instance).to receive(:meth_1).and_call_original
48
- expect(instance.meth_1).to eq(:original)
49
- end
50
-
51
- it 'ignores prior declared stubs' do
52
- instance.stub(:meth_1).and_return(:stubbed_value)
53
- instance.should_receive(:meth_1).and_call_original
54
- expect(instance.meth_1).to eq(:original)
55
- end
56
-
57
- it 'passes args and blocks through to the original method' do
58
- expect(instance).to receive(:meth_2).and_call_original
59
- value = instance.meth_2(:submitted_arg) { |a, b| [a, b] }
60
- expect(value).to eq([:submitted_arg, :additional_yielded_arg])
61
- end
62
-
63
- it 'errors when you pass through the wrong number of args' do
64
- expect(instance).to receive(:meth_1).and_call_original
65
- expect(instance).to receive(:meth_2).twice.and_call_original
66
- expect { instance.meth_1 :a }.to raise_error ArgumentError
67
- expect { instance.meth_2 {} }.to raise_error ArgumentError
68
- expect { instance.meth_2(:a, :b) {} }.to raise_error ArgumentError
69
- end
70
-
71
- it 'warns when you override an existing implementation' do
72
- expect(RSpec).to receive(:warning).with(/overriding a previous stub implementation of `meth_1`.*#{__FILE__}:#{__LINE__ + 1}/)
73
- expect(instance).to receive(:meth_1) { true }.and_call_original
74
- instance.meth_1
75
- end
76
-
77
- context "for singleton methods" do
78
- it 'works' do
79
- def instance.foo; :bar; end
80
- instance.should_receive(:foo).and_call_original
81
- expect(instance.foo).to eq(:bar)
82
- end
83
-
84
- it 'works for SimpleDelegator subclasses', :if => (RUBY_VERSION.to_f > 1.8) do
85
- instance = Class.new(SimpleDelegator).new(1)
86
- def instance.foo; :bar; end
87
- instance.should_receive(:foo).and_call_original
88
- expect(instance.foo).to eq(:bar)
89
- end
90
- end
91
-
92
- it 'works for methods added through an extended module' do
93
- instance.extend Module.new { def foo; :bar; end }
94
- instance.should_receive(:foo).and_call_original
95
- expect(instance.foo).to eq(:bar)
96
- end
97
-
98
- it "works for method added through an extended module onto a class's ancestor" do
99
- sub_sub_klass = Class.new(Class.new(klass))
100
- klass.extend Module.new { def foo; :bar; end }
101
- sub_sub_klass.should_receive(:foo).and_call_original
102
- expect(sub_sub_klass.foo).to eq(:bar)
103
- end
104
-
105
- it "finds the method on the most direct ancestor even if the method " +
106
- "is available on more distant ancestors" do
107
- klass.extend Module.new { def foo; :klass_bar; end }
108
- sub_klass = Class.new(klass)
109
- sub_klass.extend Module.new { def foo; :sub_klass_bar; end }
110
- sub_klass.should_receive(:foo).and_call_original
111
- expect(sub_klass.foo).to eq(:sub_klass_bar)
112
- end
113
-
114
- it "finds the method on the most direct singleton class ancestors even if the method " +
115
- "is available on more distant ancestors" do
116
- klass.extend Module.new { def foo; :klass_bar; end }
117
- sub_klass = Class.new(klass) { def self.foo; :sub_klass_bar; end }
118
- sub_sub_klass = Class.new(sub_klass)
119
- sub_sub_klass.should_receive(:foo).and_call_original
120
- expect(sub_sub_klass.foo).to eq(:sub_klass_bar)
121
- end
122
-
123
- context 'when using any_instance' do
124
- it 'works for instance methods defined on the class' do
125
- klass.any_instance.should_receive(:meth_1).and_call_original
126
- expect(klass.new.meth_1).to eq(:original)
127
- end
128
-
129
- it 'works for instance methods defined on the superclass of the class' do
130
- subclass = Class.new(klass)
131
- subclass.any_instance.should_receive(:meth_1).and_call_original
132
- expect(subclass.new.meth_1).to eq(:original)
133
- end
134
-
135
- it 'works when mocking the method on one class and calling the method on an instance of a subclass' do
136
- klass.any_instance.should_receive(:meth_1).and_call_original
137
- expect(Class.new(klass).new.meth_1).to eq(:original)
138
- end
139
- end
140
-
141
- it 'works for class methods defined on a superclass' do
142
- subclass = Class.new(klass)
143
- subclass.should_receive(:new_instance).and_call_original
144
- expect(subclass.new_instance).to be_a(subclass)
145
- end
146
-
147
- it 'works for class methods defined on a grandparent class' do
148
- sub_subclass = Class.new(Class.new(klass))
149
- sub_subclass.should_receive(:new_instance).and_call_original
150
- expect(sub_subclass.new_instance).to be_a(sub_subclass)
151
- end
152
-
153
- it 'works for class methods defined on the Class class' do
154
- klass.should_receive(:new).and_call_original
155
- expect(klass.new).to be_an_instance_of(klass)
156
- end
157
-
158
- it "works for instance methods defined on the object's class's superclass" do
159
- subclass = Class.new(klass)
160
- inst = subclass.new
161
- inst.should_receive(:meth_1).and_call_original
162
- expect(inst.meth_1).to eq(:original)
163
- end
164
-
165
- it 'works for aliased methods' do
166
- klass = Class.new do
167
- class << self
168
- alias alternate_new new
169
- end
170
- end
171
-
172
- klass.should_receive(:alternate_new).and_call_original
173
- expect(klass.alternate_new).to be_an_instance_of(klass)
174
- end
175
-
176
- context 'on an object that defines method_missing' do
177
- before do
178
- klass.class_exec do
179
- private
180
-
181
- def method_missing(name, *args)
182
- if name.to_s == "greet_jack"
183
- "Hello, jack"
184
- else
185
- super
186
- end
187
- end
188
- end
189
- end
190
-
191
- it 'works when the method_missing definition handles the message' do
192
- instance.should_receive(:greet_jack).and_call_original
193
- expect(instance.greet_jack).to eq("Hello, jack")
194
- end
195
-
196
- it 'works for an any_instance partial mock' do
197
- klass.any_instance.should_receive(:greet_jack).and_call_original
198
- expect(instance.greet_jack).to eq("Hello, jack")
199
- end
200
-
201
- it 'raises an error for an unhandled message for an any_instance partial mock' do
202
- klass.any_instance.should_receive(:not_a_handled_message).and_call_original
203
- expect {
204
- instance.not_a_handled_message
205
- }.to raise_error(NameError, /not_a_handled_message/)
206
- end
207
-
208
- it 'raises an error on invocation if method_missing does not handle the message' do
209
- instance.should_receive(:not_a_handled_message).and_call_original
210
-
211
- # Note: it should raise a NoMethodError (and usually does), but
212
- # due to a weird rspec-expectations issue (see #183) it sometimes
213
- # raises a `NameError` when a `be_xxx` predicate matcher has been
214
- # recently used. `NameError` is the superclass of `NoMethodError`
215
- # so this example will pass regardless.
216
- # If/when we solve the rspec-expectations issue, this can (and should)
217
- # be changed to `NoMethodError`.
218
- expect {
219
- instance.not_a_handled_message
220
- }.to raise_error(NameError, /not_a_handled_message/)
221
- end
222
- end
223
- end
224
-
225
- context "on a partial double that overrides #method" do
226
- let(:request_klass) do
227
- Struct.new(:method, :url) do
228
- def perform
229
- :the_response
230
- end
231
-
232
- def self.method
233
- :some_method
234
- end
235
- end
236
- end
237
-
238
- let(:request) { request_klass.new(:get, "http://foo.com/bar") }
239
-
240
- it 'still works even though #method has been overriden' do
241
- request.should_receive(:perform).and_call_original
242
- expect(request.perform).to eq(:the_response)
243
- end
244
-
245
- it 'works for a singleton method' do
246
- def request.perform
247
- :a_response
248
- end
249
-
250
- request.should_receive(:perform).and_call_original
251
- expect(request.perform).to eq(:a_response)
252
- end
253
- end
254
-
255
- context "on a pure test double" do
256
- let(:instance) { double }
257
-
258
- it 'raises an error even if the double object responds to the message' do
259
- expect(instance.to_s).to be_a(String)
260
- mock_expectation = instance.should_receive(:to_s)
261
- instance.to_s # to satisfy the expectation
262
-
263
- expect {
264
- mock_expectation.and_call_original
265
- }.to raise_error(/pure test double.*and_call_original.*partial double/i)
266
- end
267
- end
268
- end