rspec-mocks 3.0.0.beta1 → 3.0.0.beta2

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 (114) hide show
  1. data.tar.gz.sig +1 -1
  2. data/Changelog.md +95 -3
  3. data/README.md +27 -13
  4. data/features/README.md +15 -7
  5. data/features/argument_matchers/README.md +5 -5
  6. data/features/argument_matchers/explicit.feature +6 -6
  7. data/features/argument_matchers/general_matchers.feature +4 -4
  8. data/features/argument_matchers/type_matchers.feature +2 -2
  9. data/features/message_expectations/README.md +29 -27
  10. data/features/message_expectations/call_original.feature +0 -1
  11. data/features/message_expectations/message_chains_using_expect.feature +49 -0
  12. data/features/method_stubs/README.md +2 -1
  13. data/features/method_stubs/{any_instance.feature → allow_any_instance_of.feature} +12 -12
  14. data/features/method_stubs/{stub_chain.feature → receive_message_chain.feature} +3 -3
  15. data/features/method_stubs/to_ary.feature +1 -1
  16. data/features/mutating_constants/stub_defined_constant.feature +0 -1
  17. data/features/outside_rspec/standalone.feature +1 -1
  18. data/features/spies/spy_pure_mock_method.feature +1 -1
  19. data/features/test_frameworks/test_unit.feature +21 -10
  20. data/features/verifying_doubles/README.md +17 -0
  21. data/features/verifying_doubles/class_doubles.feature +1 -16
  22. data/features/verifying_doubles/dynamic_classes.feature +0 -1
  23. data/features/verifying_doubles/{introduction.feature → instance_doubles.feature} +41 -23
  24. data/features/verifying_doubles/partial_doubles.feature +2 -2
  25. data/lib/rspec/mocks.rb +69 -82
  26. data/lib/rspec/mocks/any_instance/expect_chain_chain.rb +35 -0
  27. data/lib/rspec/mocks/any_instance/expectation_chain.rb +1 -2
  28. data/lib/rspec/mocks/any_instance/recorder.rb +52 -18
  29. data/lib/rspec/mocks/any_instance/stub_chain.rb +1 -1
  30. data/lib/rspec/mocks/any_instance/stub_chain_chain.rb +4 -0
  31. data/lib/rspec/mocks/argument_list_matcher.rb +10 -44
  32. data/lib/rspec/mocks/argument_matchers.rb +132 -163
  33. data/lib/rspec/mocks/configuration.rb +28 -4
  34. data/lib/rspec/mocks/error_generator.rb +46 -13
  35. data/lib/rspec/mocks/example_methods.rb +13 -12
  36. data/lib/rspec/mocks/extensions/marshal.rb +1 -1
  37. data/lib/rspec/mocks/framework.rb +3 -4
  38. data/lib/rspec/mocks/instance_method_stasher.rb +2 -3
  39. data/lib/rspec/mocks/matchers/have_received.rb +8 -6
  40. data/lib/rspec/mocks/matchers/receive.rb +28 -20
  41. data/lib/rspec/mocks/matchers/receive_message_chain.rb +65 -0
  42. data/lib/rspec/mocks/matchers/receive_messages.rb +3 -2
  43. data/lib/rspec/mocks/message_chain.rb +91 -0
  44. data/lib/rspec/mocks/message_expectation.rb +86 -80
  45. data/lib/rspec/mocks/method_double.rb +2 -11
  46. data/lib/rspec/mocks/method_reference.rb +82 -23
  47. data/lib/rspec/mocks/method_signature_verifier.rb +207 -0
  48. data/lib/rspec/mocks/mutate_const.rb +34 -50
  49. data/lib/rspec/mocks/object_reference.rb +0 -1
  50. data/lib/rspec/mocks/proxy.rb +70 -13
  51. data/lib/rspec/mocks/ruby_features.rb +24 -0
  52. data/lib/rspec/mocks/space.rb +105 -31
  53. data/lib/rspec/mocks/standalone.rb +2 -2
  54. data/lib/rspec/mocks/syntax.rb +43 -8
  55. data/lib/rspec/mocks/targets.rb +16 -7
  56. data/lib/rspec/mocks/test_double.rb +41 -15
  57. data/lib/rspec/mocks/verifying_double.rb +51 -4
  58. data/lib/rspec/mocks/verifying_message_expecation.rb +12 -12
  59. data/lib/rspec/mocks/verifying_proxy.rb +32 -19
  60. data/lib/rspec/mocks/version.rb +1 -1
  61. data/spec/rspec/mocks/and_call_original_spec.rb +28 -7
  62. data/spec/rspec/mocks/and_return_spec.rb +23 -0
  63. data/spec/rspec/mocks/and_yield_spec.rb +1 -2
  64. data/spec/rspec/mocks/any_instance_spec.rb +33 -17
  65. data/spec/rspec/mocks/array_including_matcher_spec.rb +6 -6
  66. data/spec/rspec/mocks/before_all_spec.rb +132 -0
  67. data/spec/rspec/mocks/block_return_value_spec.rb +12 -1
  68. data/spec/rspec/mocks/combining_implementation_instructions_spec.rb +9 -11
  69. data/spec/rspec/mocks/configuration_spec.rb +14 -1
  70. data/spec/rspec/mocks/double_spec.rb +867 -24
  71. data/spec/rspec/mocks/example_methods_spec.rb +13 -0
  72. data/spec/rspec/mocks/extensions/marshal_spec.rb +17 -17
  73. data/spec/rspec/mocks/failing_argument_matchers_spec.rb +29 -1
  74. data/spec/rspec/mocks/hash_excluding_matcher_spec.rb +12 -12
  75. data/spec/rspec/mocks/hash_including_matcher_spec.rb +21 -17
  76. data/spec/rspec/mocks/instance_method_stasher_spec.rb +2 -3
  77. data/spec/rspec/mocks/matchers/have_received_spec.rb +7 -0
  78. data/spec/rspec/mocks/matchers/receive_message_chain_spec.rb +198 -0
  79. data/spec/rspec/mocks/matchers/receive_messages_spec.rb +2 -2
  80. data/spec/rspec/mocks/matchers/receive_spec.rb +19 -6
  81. data/spec/rspec/mocks/method_signature_verifier_spec.rb +272 -0
  82. data/spec/rspec/mocks/methods_spec.rb +0 -1
  83. data/spec/rspec/mocks/multiple_return_value_spec.rb +2 -2
  84. data/spec/rspec/mocks/mutate_const_spec.rb +24 -1
  85. data/spec/rspec/mocks/nil_expectation_warning_spec.rb +6 -22
  86. data/spec/rspec/mocks/null_object_mock_spec.rb +13 -7
  87. data/spec/rspec/mocks/options_hash_spec.rb +3 -3
  88. data/spec/rspec/mocks/{partial_mock_spec.rb → partial_double_spec.rb} +5 -2
  89. data/spec/rspec/mocks/{partial_mock_using_mocks_directly_spec.rb → partial_double_using_mocks_directly_spec.rb} +1 -1
  90. data/spec/rspec/mocks/passing_argument_matchers_spec.rb +18 -0
  91. data/spec/rspec/mocks/serialization_spec.rb +1 -0
  92. data/spec/rspec/mocks/space_spec.rb +218 -7
  93. data/spec/rspec/mocks/stub_chain_spec.rb +6 -0
  94. data/spec/rspec/mocks/stub_spec.rb +0 -6
  95. data/spec/rspec/mocks/syntax_spec.rb +19 -0
  96. data/spec/rspec/mocks/test_double_spec.rb +0 -1
  97. data/spec/rspec/mocks/verifying_double_spec.rb +281 -18
  98. data/spec/rspec/mocks/verifying_message_expecation_spec.rb +7 -6
  99. data/spec/rspec/mocks_spec.rb +168 -42
  100. data/spec/spec_helper.rb +34 -22
  101. metadata +94 -63
  102. metadata.gz.sig +0 -0
  103. checksums.yaml +0 -15
  104. checksums.yaml.gz.sig +0 -2
  105. data/features/outside_rspec/configuration.feature +0 -60
  106. data/lib/rspec/mocks/arity_calculator.rb +0 -66
  107. data/lib/rspec/mocks/errors.rb +0 -12
  108. data/lib/rspec/mocks/mock.rb +0 -7
  109. data/lib/rspec/mocks/proxy_for_nil.rb +0 -37
  110. data/lib/rspec/mocks/stub_chain.rb +0 -51
  111. data/spec/rspec/mocks/argument_expectation_spec.rb +0 -32
  112. data/spec/rspec/mocks/arity_calculator_spec.rb +0 -95
  113. data/spec/rspec/mocks/mock_space_spec.rb +0 -113
  114. data/spec/rspec/mocks/mock_spec.rb +0 -788
@@ -23,6 +23,17 @@ describe "a double declaration with a block handed to:" do
23
23
  obj.stub(:foo) { 'bar' }
24
24
  expect(obj.foo).to eq('bar')
25
25
  end
26
+
27
+ # The "receives a block" part is important: 1.8.7 has a bug that reports the
28
+ # wrong arity when a block receives a block.
29
+ it 'forwards all given args to the block, even when it receives a block' do
30
+ obj = Object.new
31
+ yielded_args = []
32
+ eval("obj.stub(:foo) { |*args, &bl| yielded_args << args }")
33
+ obj.foo(1, 2, 3)
34
+
35
+ expect(yielded_args).to eq([[1, 2, 3]])
36
+ end
26
37
  end
27
38
 
28
39
  describe "with" do
@@ -39,7 +50,7 @@ describe "a double declaration with a block handed to:" do
39
50
  end
40
51
  end
41
52
 
42
- %w[once twice ordered and_return].each do |method|
53
+ %w[once twice ordered].each do |method|
43
54
  describe method do
44
55
  it "returns the value of executing the block" do
45
56
  obj = Object.new
@@ -84,15 +84,6 @@ module RSpec
84
84
  end
85
85
  end
86
86
 
87
- it 'can combine and_yield and and_return with a block' do
88
- dbl = double
89
- dbl.stub(:foo).and_yield(5).and_return { :return }
90
-
91
- expect { |b|
92
- expect(dbl.foo(&b)).to eq(:return)
93
- }.to yield_with_args(5)
94
- end
95
-
96
87
  it 'can combine and_yield and and_raise' do
97
88
  dbl = double
98
89
  dbl.stub(:foo).and_yield(5).and_raise("boom")
@@ -171,10 +162,18 @@ module RSpec
171
162
  end
172
163
 
173
164
  it 'warns when the inner implementation block is overriden' do
174
- expect(RSpec).to receive(:warning).with(/overriding a previous implementation/)
165
+ expect(RSpec).to receive(:warning).with(/overriding a previous stub implementation of `foo`.*#{__FILE__}:#{__LINE__ + 1}/)
175
166
  double.stub(:foo).with(:arg) { :with_block }.at_least(:once) { :at_least_block }
176
167
  end
177
168
 
169
+ it "does not warn about overriding the stub when `:with` is chained off the block" do
170
+ expect(RSpec).not_to receive(:warning)
171
+
172
+ obj = Object.new
173
+ stub = obj.stub(:foo) { }
174
+ stub.with(1)
175
+ end
176
+
178
177
  it 'can combine and_call_original, with, and_return' do
179
178
  obj = Struct.new(:value).new('original')
180
179
  obj.stub(:value).and_call_original
@@ -203,4 +202,3 @@ module RSpec
203
202
  end
204
203
  end
205
204
  end
206
-
@@ -162,6 +162,20 @@ module RSpec
162
162
  o2.stub(:faces)
163
163
  end
164
164
 
165
+ it "warns about unstubbing once, regardless of how many times it is called" do
166
+ expect(RSpec).to receive(:deprecate).with(/Using.*without explicitly enabling/,
167
+ {:replacement => "`allow(...).to_receive(...).and_call_original` or explicitly enable `:should`"})
168
+ o = Object.new
169
+ o2 = Object.new
170
+
171
+ allow(o).to receive(:faces)
172
+ allow(o2).to receive(:faces)
173
+
174
+ o.unstub(:faces)
175
+ o2.unstub(:faces)
176
+ end
177
+
178
+
165
179
  it "doesn't warn about stubbing after a reset and setting should" do
166
180
  expect(RSpec).not_to receive(:deprecate)
167
181
  RSpec::Mocks.configuration.reset_syntaxes_to_default
@@ -226,4 +240,3 @@ module RSpec
226
240
  end
227
241
  end
228
242
  end
229
-
@@ -1,31 +1,874 @@
1
- require "spec_helper"
1
+ require 'spec_helper'
2
2
 
3
- describe "double" do
4
- it "is an alias for stub and mock" do
5
- expect(double()).to be_a(RSpec::Mocks::Mock)
6
- end
3
+ module RSpec
4
+ module Mocks
5
+ describe Double do
6
+ before(:each) { @double = double("test double") }
7
+ after(:each) { reset @double }
7
8
 
8
- it "uses 'Double' in failure messages" do
9
- double = double('name')
10
- expect {double.foo}.to raise_error(/Double "name" received/)
11
- end
9
+ it "has method_missing as private" do
10
+ expect(RSpec::Mocks::Double.private_instance_methods).to include_method(:method_missing)
11
+ end
12
12
 
13
- it "hides internals in its inspect representation" do
14
- m = double('cup')
15
- expect(m.inspect).to match(/#<RSpec::Mocks::Mock:0x[a-f0-9.]+ @name="cup">/)
16
- end
13
+ it "does not respond_to? method_missing (because it's private)" do
14
+ expect(RSpec::Mocks::Double.new).not_to respond_to(:method_missing)
15
+ end
17
16
 
18
- it 'restores standard object methods on reset' do
19
- dbl = double(:tainted? => true)
20
- expect(dbl.tainted?).to eq(true)
21
- reset dbl
22
- expect(dbl.tainted?).to eq(false)
23
- end
17
+ it "uses 'Double' in failure messages" do
18
+ double = double('name')
19
+ expect { double.foo }.to raise_error(/Double "name" received/)
20
+ end
21
+
22
+ it "hides internals in its inspect representation" do
23
+ m = double('cup')
24
+ expect(m.inspect).to match(/#<RSpec::Mocks::Double:0x[a-f0-9.]+ @name="cup">/)
25
+ end
26
+
27
+ it 'does not blow up when resetting standard object methods' do
28
+ dbl = double(:tainted? => true)
29
+ expect(dbl.tainted?).to eq(true)
30
+ expect { reset dbl }.not_to raise_error
31
+ end
32
+
33
+ it 'does not get string vs symbol messages confused' do
34
+ dbl = double("foo" => 1)
35
+ allow(dbl).to receive(:foo).and_return(2)
36
+ expect(dbl.foo).to eq(2)
37
+ expect { reset dbl }.not_to raise_error
38
+ end
39
+
40
+ it 'allows string representation of methods in constructor' do
41
+ dbl = double('foo' => 1)
42
+ expect(dbl.foo).to eq(1)
43
+ end
44
+
45
+ it 'allows setter methods to be stubbed' do
46
+ dbl = double('foo=' => 1)
47
+
48
+ # Note the specified return value is thrown away. This is a Ruby semantics
49
+ # thing. You cannot change the return value of assignment.
50
+ expect(dbl.foo = "bar").to eq("bar")
51
+ end
52
+
53
+ it 'allows `send` to be stubbed' do
54
+ dbl = double
55
+ allow(dbl).to receive(:send).and_return("received")
56
+ expect(dbl.send(:some_msg)).to eq("received")
57
+ end
58
+
59
+ context "after it has been torn down" do
60
+ let(:dbl) { double }
61
+
62
+ before do
63
+ expect(dbl).to receive(:foo).at_least(:once)
64
+ allow(dbl).to receive(:bar)
65
+ dbl.foo
66
+
67
+ RSpec::Mocks.verify
68
+ RSpec::Mocks.teardown
69
+ RSpec::Mocks.setup
70
+ end
71
+
72
+ it 'disallows previously mocked methods' do
73
+ expect { dbl.foo }.to raise_error(ExpiredTestDoubleError)
74
+ end
75
+
76
+ it 'disallows previously stubbed methods' do
77
+ expect { dbl.bar }.to raise_error(ExpiredTestDoubleError)
78
+ end
79
+
80
+ it 'disallows stubbing new methods (with receive)' do
81
+ expect {
82
+ allow(dbl).to receive(:bazz)
83
+ }.to raise_error(ExpiredTestDoubleError)
84
+ end
85
+
86
+ it 'disallows stubbing new methods (with receive_messages)' do
87
+ expect {
88
+ allow(dbl).to receive_messages(:bazz => 3)
89
+ }.to raise_error(ExpiredTestDoubleError)
90
+ end
91
+
92
+ it 'disallows stubbing new message chains' do
93
+ expect {
94
+ allow(dbl).to receive_message_chain(:bazz, :bam, :goo)
95
+ }.to raise_error(ExpiredTestDoubleError)
96
+ end
97
+
98
+ it 'disallows mocking new methods' do
99
+ expect {
100
+ expect(dbl).to receive(:bazz)
101
+ }.to raise_error(ExpiredTestDoubleError)
102
+ end
103
+
104
+ it 'disallows being turned into a null object' do
105
+ expect { dbl.as_null_object }.to raise_error(ExpiredTestDoubleError)
106
+ end
107
+
108
+ it 'disallows being checked for nullness' do
109
+ expect { dbl.null_object? }.to raise_error(ExpiredTestDoubleError)
110
+ end
111
+ end
112
+
113
+ it "reports line number of expectation of unreceived message" do
114
+ expected_error_line = __LINE__; @double.should_receive(:wont_happen).with("x", 3)
115
+ begin
116
+ verify @double
117
+ violated
118
+ rescue RSpec::Mocks::MockExpectationError => e
119
+ # NOTE - this regexp ended w/ $, but jruby adds extra info at the end of the line
120
+ expect(e.backtrace[0]).to match(/#{File.basename(__FILE__)}:#{expected_error_line}/)
121
+ end
122
+ end
123
+
124
+ it "reports line number of expectation of unreceived message after #should_receive after similar stub" do
125
+ @double.stub(:wont_happen)
126
+ expected_error_line = __LINE__; @double.should_receive(:wont_happen).with("x", 3)
127
+ begin
128
+ verify @double
129
+ violated
130
+ rescue RSpec::Mocks::MockExpectationError => e
131
+ # NOTE - this regexp ended w/ $, but jruby adds extra info at the end of the line
132
+ expect(e.backtrace[0]).to match(/#{File.basename(__FILE__)}:#{expected_error_line}/)
133
+ end
134
+ end
135
+
136
+ it "passes when not receiving message specified as not to be received" do
137
+ @double.should_not_receive(:not_expected)
138
+ verify @double
139
+ end
140
+
141
+ it "prevents confusing double-negative expressions involving `never`" do
142
+ expect {
143
+ @double.should_not_receive(:not_expected).never
144
+ }.to raise_error(/trying to negate it again/)
145
+ end
146
+
147
+ it "warns when `and_return` is called on a negative expectation" do
148
+ expect {
149
+ @double.should_not_receive(:do_something).and_return(1)
150
+ }.to raise_error(/not supported/)
151
+
152
+ expect {
153
+ expect(@double).not_to receive(:do_something).and_return(1)
154
+ }.to raise_error(/not supported/)
155
+
156
+ expect {
157
+ expect(@double).to receive(:do_something).never.and_return(1)
158
+ }.to raise_error(/not supported/)
159
+ end
160
+
161
+ it "passes when receiving message specified as not to be received with different args" do
162
+ @double.should_not_receive(:message).with("unwanted text")
163
+ @double.should_receive(:message).with("other text")
164
+ @double.message "other text"
165
+ verify @double
166
+ end
167
+
168
+ it "fails when receiving message specified as not to be received" do
169
+ @double.should_not_receive(:not_expected)
170
+ expect {
171
+ @double.not_expected
172
+ violated
173
+ }.to raise_error(
174
+ RSpec::Mocks::MockExpectationError,
175
+ %Q|(Double "test double").not_expected(no args)\n expected: 0 times with any arguments\n received: 1 time|
176
+ )
177
+ end
178
+
179
+ it "fails when receiving message specified as not to be received with args" do
180
+ @double.should_not_receive(:not_expected).with("unexpected text")
181
+ expect {
182
+ @double.not_expected("unexpected text")
183
+ violated
184
+ }.to raise_error(
185
+ RSpec::Mocks::MockExpectationError,
186
+ %Q|(Double "test double").not_expected("unexpected text")\n expected: 0 times with arguments: ("unexpected text")\n received: 1 time with arguments: ("unexpected text")|
187
+ )
188
+ end
189
+
190
+ it "fails when array arguments do not match" do
191
+ @double.should_not_receive(:not_expected).with(["do not want"])
192
+ expect {
193
+ @double.not_expected(["do not want"])
194
+ violated
195
+ }.to raise_error(
196
+ RSpec::Mocks::MockExpectationError,
197
+ %Q|(Double "test double").not_expected(["do not want"])\n expected: 0 times with arguments: (["do not want"])\n received: 1 time with arguments: (["do not want"])|
198
+ )
199
+ end
200
+
201
+ context "when specifying a message should not be received with specific args" do
202
+ context "using `should_not_receive`" do
203
+ it 'passes when receiving the message with different args' do
204
+ @double.should_not_receive(:not_expected).with("unexpected text")
205
+ @double.not_expected "really unexpected text"
206
+ verify @double
207
+ end
208
+ end
209
+
210
+ context "using `should_receive().never`" do
211
+ it 'passes when receiving the message with different args' do
212
+ @double.should_receive(:not_expected).with("unexpected text").never
213
+ @double.not_expected "really unexpected text"
214
+ verify @double
215
+ end
216
+ end
217
+ end
218
+
219
+ it 'does not get confused when `should_not_received` is used with a string and symbol message' do
220
+ @double.stub(:foo) { 3 }
221
+ @double.should_not_receive(:foo).with(1)
222
+ @double.should_not_receive("foo").with(2)
223
+
224
+ expect(@double.foo).to eq(3)
225
+ verify @double
226
+ end
227
+
228
+ it 'does not get confused when `should_received` is used with a string and symbol message' do
229
+ @double.should_receive(:foo).with(1)
230
+ @double.should_receive("foo").with(2)
231
+
232
+ @double.foo(1)
233
+ @double.foo(2)
234
+
235
+ verify @double
236
+ end
237
+
238
+ it "allows parameter as return value" do
239
+ @double.should_receive(:something).with("a","b","c").and_return("booh")
240
+ expect(@double.something("a","b","c")).to eq "booh"
241
+ verify @double
242
+ end
243
+
244
+ it "returns the previously stubbed value if no return value is set" do
245
+ @double.stub(:something).with("a","b","c").and_return(:stubbed_value)
246
+ @double.should_receive(:something).with("a","b","c")
247
+ expect(@double.something("a","b","c")).to eq :stubbed_value
248
+ verify @double
249
+ end
250
+
251
+ it "returns nil if no return value is set and there is no previously stubbed value" do
252
+ @double.should_receive(:something).with("a","b","c")
253
+ expect(@double.something("a","b","c")).to be_nil
254
+ verify @double
255
+ end
256
+
257
+ it "raises exception if args don't match when method called" do
258
+ @double.should_receive(:something).with("a","b","c").and_return("booh")
259
+ expect {
260
+ @double.something("a","d","c")
261
+ violated
262
+ }.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"test double\" received :something with unexpected arguments\n expected: (\"a\", \"b\", \"c\")\n got: (\"a\", \"d\", \"c\")")
263
+ end
264
+
265
+ describe "even when a similar expectation with different arguments exist" do
266
+ it "raises exception if args don't match when method called, correctly reporting the offending arguments" do
267
+ @double.should_receive(:something).with("a","b","c").once
268
+ @double.should_receive(:something).with("z","x","c").once
269
+ expect {
270
+ @double.something("a","b","c")
271
+ @double.something("z","x","g")
272
+ }.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"test double\" received :something with unexpected arguments\n expected: (\"z\", \"x\", \"c\")\n got: (\"z\", \"x\", \"g\")")
273
+ end
274
+ end
275
+
276
+ it "raises exception if args don't match when method called even when the method is stubbed" do
277
+ @double.stub(:something)
278
+ @double.should_receive(:something).with("a","b","c")
279
+ expect {
280
+ @double.something("a","d","c")
281
+ verify @double
282
+ }.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"test double\" received :something with unexpected arguments\n expected: (\"a\", \"b\", \"c\")\n got: (\"a\", \"d\", \"c\")")
283
+ end
284
+
285
+ it "raises exception if args don't match when method called even when using null_object" do
286
+ @double = double("test double").as_null_object
287
+ @double.should_receive(:something).with("a","b","c")
288
+ expect {
289
+ @double.something("a","d","c")
290
+ verify @double
291
+ }.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"test double\" received :something with unexpected arguments\n expected: (\"a\", \"b\", \"c\")\n got: (\"a\", \"d\", \"c\")")
292
+ end
293
+
294
+ describe 'with a method that has a default argument' do
295
+ it "raises an exception if the arguments don't match when the method is called, correctly reporting the offending arguments" do
296
+ def @double.method_with_default_argument(arg={}); end
297
+ @double.should_receive(:method_with_default_argument).with({})
298
+
299
+ expect {
300
+ @double.method_with_default_argument(nil)
301
+ verify @double
302
+ }.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"test double\" received :method_with_default_argument with unexpected arguments\n expected: ({})\n got: (nil)")
303
+ end
304
+ end
305
+
306
+ it "fails if unexpected method called" do
307
+ expect {
308
+ @double.something("a","b","c")
309
+ violated
310
+ }.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"test double\" received unexpected message :something with (\"a\", \"b\", \"c\")")
311
+ end
312
+
313
+ it "uses block for expectation if provided" do
314
+ @double.should_receive(:something) do | a, b |
315
+ expect(a).to eq "a"
316
+ expect(b).to eq "b"
317
+ "booh"
318
+ end
319
+ expect(@double.something("a", "b")).to eq "booh"
320
+ verify @double
321
+ end
322
+
323
+ it "fails if expectation block fails" do
324
+ @double.should_receive(:something) do |bool|
325
+ expect(bool).to be_truthy
326
+ end
327
+
328
+ expect {
329
+ @double.something false
330
+ }.to raise_error(RSpec::Expectations::ExpectationNotMetError)
331
+ end
332
+
333
+ it "is wrappable in an array" do
334
+ with_isolated_stderr do
335
+ expect( Array(@double) ).to eq([@double])
336
+ end
337
+ end
338
+
339
+ it "is wrappable in an array when a null object" do
340
+ with_isolated_stderr do
341
+ expect( Array(@double.as_null_object) ).to eq [@double]
342
+ end
343
+ end
344
+
345
+ it "responds to to_ary as a null object" do
346
+ expect(@double.as_null_object.to_ary).to eq nil
347
+ end
348
+
349
+ it "responds to to_a as a null object" do
350
+ if RUBY_VERSION.to_f > 1.8
351
+ expect(@double.as_null_object.to_a).to eq nil
352
+ else
353
+ with_isolated_stderr do
354
+ expect(@double.as_null_object.to_a).to eq [@double]
355
+ end
356
+ end
357
+ end
358
+
359
+ it "passes proc to expectation block without an argument" do
360
+ @double.should_receive(:foo) { |&block| expect(block.call).to eq(:bar) }
361
+ @double.foo { :bar }
362
+ end
363
+
364
+ it "passes proc to expectation block with an argument" do
365
+ @double.should_receive(:foo) { |arg, &block| expect(block.call).to eq(:bar) }
366
+ @double.foo(:arg) { :bar }
367
+ end
368
+
369
+ it "passes proc to stub block without an argurment" do
370
+ @double.stub(:foo) { |&block| expect(block.call).to eq(:bar) }
371
+ @double.foo { :bar }
372
+ end
373
+
374
+ it "passes proc to stub block with an argument" do
375
+ @double.stub(:foo) { |arg, &block| expect(block.call).to eq(:bar) }
376
+ @double.foo(:arg) { :bar }
377
+ end
378
+
379
+ it "fails right away when method defined as never is received" do
380
+ @double.should_receive(:not_expected).never
381
+ expect { @double.not_expected }.
382
+ to raise_error(RSpec::Mocks::MockExpectationError,
383
+ %Q|(Double "test double").not_expected(no args)\n expected: 0 times with any arguments\n received: 1 time|
384
+ )
385
+ end
386
+
387
+ it "raises RuntimeError by default" do
388
+ @double.should_receive(:something).and_raise
389
+ expect { @double.something }.to raise_error(RuntimeError)
390
+ end
391
+
392
+ it "raises RuntimeError with a message by default" do
393
+ @double.should_receive(:something).and_raise("error message")
394
+ expect { @double.something }.to raise_error(RuntimeError, "error message")
395
+ end
396
+
397
+ it "raises an exception of a given type without an error message" do
398
+ @double.should_receive(:something).and_raise(StandardError)
399
+ expect { @double.something }.to raise_error(StandardError)
400
+ end
401
+
402
+ it "raises an exception of a given type with a message" do
403
+ @double.should_receive(:something).and_raise(RuntimeError, "error message")
404
+ expect { @double.something }.to raise_error(RuntimeError, "error message")
405
+ end
406
+
407
+ it "raises a given instance of an exception" do
408
+ @double.should_receive(:something).and_raise(RuntimeError.new("error message"))
409
+ expect { @double.something }.to raise_error(RuntimeError, "error message")
410
+ end
411
+
412
+ class OutOfGas < StandardError
413
+ attr_reader :amount, :units
414
+ def initialize(amount, units)
415
+ @amount = amount
416
+ @units = units
417
+ end
418
+ end
419
+
420
+ it "raises a given instance of an exception with arguments other than the standard 'message'" do
421
+ @double.should_receive(:something).and_raise(OutOfGas.new(2, :oz))
422
+
423
+ begin
424
+ @double.something
425
+ fail "OutOfGas was not raised"
426
+ rescue OutOfGas => e
427
+ expect(e.amount).to eq 2
428
+ expect(e.units).to eq :oz
429
+ end
430
+ end
431
+
432
+ it "does not raise when told to if args dont match" do
433
+ @double.should_receive(:something).with(2).and_raise(RuntimeError)
434
+ expect {
435
+ @double.something 1
436
+ }.to raise_error(RSpec::Mocks::MockExpectationError)
437
+ end
438
+
439
+ it "throws when told to" do
440
+ @double.should_receive(:something).and_throw(:blech)
441
+ expect {
442
+ @double.something
443
+ }.to throw_symbol(:blech)
444
+ end
445
+
446
+ it "ignores args on any args" do
447
+ @double.should_receive(:something).at_least(:once).with(any_args)
448
+ @double.something
449
+ @double.something 1
450
+ @double.something "a", 2
451
+ @double.something [], {}, "joe", 7
452
+ verify @double
453
+ end
454
+
455
+ it "fails on no args if any args received" do
456
+ @double.should_receive(:something).with(no_args())
457
+ expect {
458
+ @double.something 1
459
+ }.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"test double\" received :something with unexpected arguments\n expected: (no args)\n got: (1)")
460
+ end
461
+
462
+ it "fails when args are expected but none are received" do
463
+ @double.should_receive(:something).with(1)
464
+ expect {
465
+ @double.something
466
+ }.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"test double\" received :something with unexpected arguments\n expected: (1)\n got: (no args)")
467
+ end
468
+
469
+ it "returns value from block by default" do
470
+ @double.stub(:method_that_yields).and_yield
471
+ value = @double.method_that_yields { :returned_obj }
472
+ expect(value).to eq :returned_obj
473
+ verify @double
474
+ end
475
+
476
+ it "yields 0 args to blocks that take a variable number of arguments" do
477
+ @double.should_receive(:yield_back).with(no_args()).once.and_yield
478
+ a = nil
479
+ @double.yield_back {|*x| a = x}
480
+ expect(a).to eq []
481
+ verify @double
482
+ end
483
+
484
+ it "yields 0 args multiple times to blocks that take a variable number of arguments" do
485
+ @double.should_receive(:yield_back).once.with(no_args()).once.and_yield.
486
+ and_yield
487
+ b = []
488
+ @double.yield_back {|*a| b << a}
489
+ expect(b).to eq [ [], [] ]
490
+ verify @double
491
+ end
492
+
493
+ it "yields one arg to blocks that take a variable number of arguments" do
494
+ @double.should_receive(:yield_back).with(no_args()).once.and_yield(99)
495
+ a = nil
496
+ @double.yield_back {|*x| a = x}
497
+ expect(a).to eq [99]
498
+ verify @double
499
+ end
500
+
501
+ it "yields one arg 3 times consecutively to blocks that take a variable number of arguments" do
502
+ @double.should_receive(:yield_back).once.with(no_args()).once.and_yield(99).
503
+ and_yield(43).
504
+ and_yield("something fruity")
505
+ b = []
506
+ @double.yield_back {|*a| b << a}
507
+ expect(b).to eq [[99], [43], ["something fruity"]]
508
+ verify @double
509
+ end
510
+
511
+ it "yields many args to blocks that take a variable number of arguments" do
512
+ @double.should_receive(:yield_back).with(no_args()).once.and_yield(99, 27, "go")
513
+ a = nil
514
+ @double.yield_back {|*x| a = x}
515
+ expect(a).to eq [99, 27, "go"]
516
+ verify @double
517
+ end
518
+
519
+ it "yields many args 3 times consecutively to blocks that take a variable number of arguments" do
520
+ @double.should_receive(:yield_back).once.with(no_args()).once.and_yield(99, :green, "go").
521
+ and_yield("wait", :amber).
522
+ and_yield("stop", 12, :red)
523
+ b = []
524
+ @double.yield_back {|*a| b << a}
525
+ expect(b).to eq [[99, :green, "go"], ["wait", :amber], ["stop", 12, :red]]
526
+ verify @double
527
+ end
528
+
529
+ it "yields single value" do
530
+ @double.should_receive(:yield_back).with(no_args()).once.and_yield(99)
531
+ a = nil
532
+ @double.yield_back {|x| a = x}
533
+ expect(a).to eq 99
534
+ verify @double
535
+ end
536
+
537
+ it "yields single value 3 times consecutively" do
538
+ @double.should_receive(:yield_back).once.with(no_args()).once.and_yield(99).
539
+ and_yield(43).
540
+ and_yield("something fruity")
541
+ b = []
542
+ @double.yield_back {|a| b << a}
543
+ expect(b).to eq [99, 43, "something fruity"]
544
+ verify @double
545
+ end
546
+
547
+ it "yields two values" do
548
+ @double.should_receive(:yield_back).with(no_args()).once.and_yield('wha', 'zup')
549
+ a, b = nil
550
+ @double.yield_back {|x,y| a=x; b=y}
551
+ expect(a).to eq 'wha'
552
+ expect(b).to eq 'zup'
553
+ verify @double
554
+ end
555
+
556
+ it "yields two values 3 times consecutively" do
557
+ @double.should_receive(:yield_back).once.with(no_args()).once.and_yield('wha', 'zup').
558
+ and_yield('not', 'down').
559
+ and_yield(14, 65)
560
+ c = []
561
+ @double.yield_back {|a,b| c << [a, b]}
562
+ expect(c).to eq [['wha', 'zup'], ['not', 'down'], [14, 65]]
563
+ verify @double
564
+ end
565
+
566
+ it "fails when calling yielding method with wrong arity" do
567
+ @double.should_receive(:yield_back).with(no_args()).once.and_yield('wha', 'zup')
568
+ expect {
569
+ @double.yield_back {|a|}
570
+ }.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"test double\" yielded |\"wha\", \"zup\"| to block with arity of 1")
571
+ end
572
+
573
+ if kw_args_supported?
574
+ it 'fails when calling yielding method with invalid kw args' do
575
+ @double.should_receive(:yield_back).and_yield(:x => 1, :y => 2)
576
+ expect {
577
+ eval("@double.yield_back { |x: 1| }")
578
+ }.to raise_error(RSpec::Mocks::MockExpectationError,
579
+ 'Double "test double" yielded |{:x=>1, :y=>2}| to block with optional keyword args (:x)')
580
+ end
581
+ end
582
+
583
+ it "fails when calling yielding method consecutively with wrong arity" do
584
+ @double.should_receive(:yield_back).once.with(no_args()).once.and_yield('wha', 'zup').
585
+ and_yield('down').
586
+ and_yield(14, 65)
587
+ expect {
588
+ c = []
589
+ @double.yield_back {|a,b| c << [a, b]}
590
+ }.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"test double\" yielded |\"down\"| to block with arity of 2")
591
+ end
592
+
593
+ it "fails when calling yielding method without block" do
594
+ @double.should_receive(:yield_back).with(no_args()).once.and_yield('wha', 'zup')
595
+ expect {
596
+ @double.yield_back
597
+ }.to raise_error(RSpec::Mocks::MockExpectationError, "Double \"test double\" asked to yield |[\"wha\", \"zup\"]| but no block was passed")
598
+ end
599
+
600
+ it "is able to double send" do
601
+ @double.should_receive(:send).with(any_args)
602
+ @double.send 'hi'
603
+ verify @double
604
+ end
605
+
606
+ it "is able to raise from method calling yielding double" do
607
+ @double.should_receive(:yield_me).and_yield 44
608
+
609
+ expect {
610
+ @double.yield_me do |x|
611
+ raise "Bang"
612
+ end
613
+ }.to raise_error(StandardError, "Bang")
614
+
615
+ verify @double
616
+ end
617
+
618
+ it "clears expectations after verify" do
619
+ @double.should_receive(:foobar)
620
+ @double.foobar
621
+ verify @double
622
+ expect {
623
+ @double.foobar
624
+ }.to raise_error(RSpec::Mocks::MockExpectationError, %q|Double "test double" received unexpected message :foobar with (no args)|)
625
+ end
626
+
627
+ it "restores objects to their original state on rspec_reset" do
628
+ double = double("this is a double")
629
+ double.should_receive(:blah)
630
+ reset double
631
+ verify double #should throw if reset didn't work
632
+ end
633
+
634
+ it "temporarily replaces a method stub on a double" do
635
+ @double.stub(:msg).and_return(:stub_value)
636
+ @double.should_receive(:msg).with(:arg).and_return(:double_value)
637
+ expect(@double.msg(:arg)).to equal(:double_value)
638
+ expect(@double.msg).to equal(:stub_value)
639
+ expect(@double.msg).to equal(:stub_value)
640
+ verify @double
641
+ end
642
+
643
+ it "does not require a different signature to replace a method stub" do
644
+ @double.stub(:msg).and_return(:stub_value)
645
+ @double.should_receive(:msg).and_return(:double_value)
646
+ expect(@double.msg(:arg)).to equal(:double_value)
647
+ expect(@double.msg).to equal(:stub_value)
648
+ expect(@double.msg).to equal(:stub_value)
649
+ verify @double
650
+ end
651
+
652
+ it "raises an error when a previously stubbed method has a negative expectation" do
653
+ @double.stub(:msg).and_return(:stub_value)
654
+ @double.should_not_receive(:msg)
655
+ expect { @double.msg(:arg) }.to raise_error(RSpec::Mocks::MockExpectationError)
656
+ end
657
+
658
+ it "temporarily replaces a method stub on a non-double" do
659
+ non_double = Object.new
660
+ non_double.stub(:msg).and_return(:stub_value)
661
+ non_double.should_receive(:msg).with(:arg).and_return(:double_value)
662
+ expect(non_double.msg(:arg)).to equal(:double_value)
663
+ expect(non_double.msg).to equal(:stub_value)
664
+ expect(non_double.msg).to equal(:stub_value)
665
+ verify non_double
666
+ end
667
+
668
+ it "returns the stubbed value when no new value specified" do
669
+ @double.stub(:msg).and_return(:stub_value)
670
+ @double.should_receive(:msg)
671
+ expect(@double.msg).to equal(:stub_value)
672
+ verify @double
673
+ end
674
+
675
+ it "returns the stubbed value when stubbed with args and no new value specified" do
676
+ @double.stub(:msg).with(:arg).and_return(:stub_value)
677
+ @double.should_receive(:msg).with(:arg)
678
+ expect(@double.msg(:arg)).to equal(:stub_value)
679
+ verify @double
680
+ end
681
+
682
+ it "does not mess with the stub's yielded values when also doubleed" do
683
+ @double.stub(:yield_back).and_yield(:stub_value)
684
+ @double.should_receive(:yield_back).and_yield(:double_value)
685
+ @double.yield_back{|v| expect(v).to eq :double_value }
686
+ @double.yield_back{|v| expect(v).to eq :stub_value }
687
+ verify @double
688
+ end
689
+
690
+ it "can yield multiple times when told to do so" do
691
+ @double.stub(:foo).and_yield(:stub_value)
692
+ @double.should_receive(:foo).and_yield(:first_yield).and_yield(:second_yield)
693
+
694
+ expect { |b| @double.foo(&b) }.to yield_successive_args(:first_yield, :second_yield)
695
+ expect { |b| @double.foo(&b) }.to yield_with_args(:stub_value)
696
+
697
+ verify @double
698
+ end
699
+
700
+ it "assigns stub return values" do
701
+ double = RSpec::Mocks::Double.new('name', :message => :response)
702
+ expect(double.message).to eq :response
703
+ end
704
+
705
+ describe "a double message receiving a block" do
706
+ before(:each) do
707
+ @double = double("double")
708
+ @calls = 0
709
+ end
710
+
711
+ def add_call
712
+ @calls = @calls + 1
713
+ end
714
+
715
+ it "calls the block after #should_receive" do
716
+ @double.should_receive(:foo) { add_call }
717
+
718
+ @double.foo
719
+
720
+ expect(@calls).to eq 1
721
+ end
722
+
723
+ it "calls the block after #should_receive after a similar stub" do
724
+ @double.stub(:foo).and_return(:bar)
725
+ @double.should_receive(:foo) { add_call }
726
+
727
+ @double.foo
728
+
729
+ expect(@calls).to eq 1
730
+ end
731
+
732
+ it "calls the block after #once" do
733
+ @double.should_receive(:foo).once { add_call }
734
+
735
+ @double.foo
736
+
737
+ expect(@calls).to eq 1
738
+ end
739
+
740
+ it "calls the block after #twice" do
741
+ @double.should_receive(:foo).twice { add_call }
742
+
743
+ @double.foo
744
+ @double.foo
745
+
746
+ expect(@calls).to eq 2
747
+ end
748
+
749
+ it "calls the block after #times" do
750
+ @double.should_receive(:foo).exactly(10).times { add_call }
751
+
752
+ (1..10).each { @double.foo }
753
+
754
+ expect(@calls).to eq 10
755
+ end
756
+
757
+ it "calls the block after #ordered" do
758
+ @double.should_receive(:foo).ordered { add_call }
759
+ @double.should_receive(:bar).ordered { add_call }
760
+
761
+ @double.foo
762
+ @double.bar
763
+
764
+ expect(@calls).to eq 2
765
+ end
766
+ end
767
+
768
+ describe 'string representation generated by #to_s' do
769
+ it 'does not contain < because that might lead to invalid HTML in some situations' do
770
+ double = double("Dog")
771
+ valid_html_str = "#{double}"
772
+ expect(valid_html_str).not_to include('<')
773
+ end
774
+ end
775
+
776
+ describe "#to_str", :unless => RUBY_VERSION == '1.9.2' do
777
+ it "should not respond to #to_str to avoid being coerced to strings by the runtime" do
778
+ double = double("Foo")
779
+ expect { double.to_str }.to raise_error(
780
+ RSpec::Mocks::MockExpectationError,
781
+ 'Double "Foo" received unexpected message :to_str with (no args)')
782
+ end
783
+ end
784
+
785
+ describe "double created with no name" do
786
+ it "does not use a name in a failure message" do
787
+ double = double()
788
+ expect {double.foo}.to raise_error(/Double received/)
789
+ end
790
+
791
+ it "does respond to initially stubbed methods" do
792
+ double = double(:foo => "woo", :bar => "car")
793
+ expect(double.foo).to eq "woo"
794
+ expect(double.bar).to eq "car"
795
+ end
796
+ end
797
+
798
+ describe "==" do
799
+ it "sends '== self' to the comparison object" do
800
+ first = double('first')
801
+ second = double('second')
802
+
803
+ first.should_receive(:==).with(second)
804
+ second == first
805
+ end
806
+ end
807
+
808
+ describe "with" do
809
+ before { @double = double('double') }
810
+ context "with args" do
811
+ context "with matching args" do
812
+ it "passes" do
813
+ @double.should_receive(:foo).with('bar')
814
+ @double.foo('bar')
815
+ end
816
+ end
817
+
818
+ context "with non-matching args" do
819
+ it "fails" do
820
+ @double.should_receive(:foo).with('bar')
821
+ expect do
822
+ @double.foo('baz')
823
+ end.to raise_error
824
+ reset @double
825
+ end
826
+ end
827
+
828
+ context "with non-matching doubles" do
829
+ it "fails" do
830
+ d1 = double('1')
831
+ d2 = double('2')
832
+ @double.should_receive(:foo).with(d1)
833
+ expect do
834
+ @double.foo(d2)
835
+ end.to raise_error
836
+ reset @double
837
+ end
838
+ end
839
+
840
+ context "with non-matching doubles as_null_object" do
841
+ it "fails" do
842
+ d1 = double('1').as_null_object
843
+ d2 = double('2').as_null_object
844
+ @double.should_receive(:foo).with(d1)
845
+ expect do
846
+ @double.foo(d2)
847
+ end.to raise_error
848
+ reset @double
849
+ end
850
+ end
851
+ end
852
+
853
+ context "with a block" do
854
+ context "with matching args" do
855
+ it "returns the result of the block" do
856
+ @double.should_receive(:foo).with('bar') { 'baz' }
857
+ expect(@double.foo('bar')).to eq('baz')
858
+ end
859
+ end
24
860
 
25
- it 'does not get string vs symbol messages confused' do
26
- dbl = double("foo" => 1)
27
- allow(dbl).to receive(:foo).and_return(2)
28
- expect(dbl.foo).to eq(2)
29
- expect { reset dbl }.not_to raise_error
861
+ context "with non-matching args" do
862
+ it "fails" do
863
+ @double.should_receive(:foo).with('bar') { 'baz' }
864
+ expect do
865
+ expect(@double.foo('wrong')).to eq('baz')
866
+ end.to raise_error(/received :foo with unexpected arguments/)
867
+ reset @double
868
+ end
869
+ end
870
+ end
871
+ end
872
+ end
30
873
  end
31
874
  end