rspec-mocks 3.0.0.beta1 → 3.0.0.beta2

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