redinger-rr 0.10.3
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.
- data/CHANGES +221 -0
- data/README.rdoc +343 -0
- data/Rakefile +88 -0
- data/VERSION.yml +4 -0
- data/lib/rr.rb +88 -0
- data/lib/rr/adapters/rr_methods.rb +122 -0
- data/lib/rr/adapters/rspec.rb +59 -0
- data/lib/rr/adapters/test_unit.rb +29 -0
- data/lib/rr/double.rb +152 -0
- data/lib/rr/double_definitions/child_double_definition_creator.rb +27 -0
- data/lib/rr/double_definitions/double_definition.rb +348 -0
- data/lib/rr/double_definitions/double_definition_creator.rb +167 -0
- data/lib/rr/double_definitions/double_definition_creator_proxy.rb +37 -0
- data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +15 -0
- data/lib/rr/double_definitions/strategies/implementation/proxy.rb +62 -0
- data/lib/rr/double_definitions/strategies/implementation/reimplementation.rb +14 -0
- data/lib/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation.rb +17 -0
- data/lib/rr/double_definitions/strategies/scope/instance.rb +15 -0
- data/lib/rr/double_definitions/strategies/scope/instance_of_class.rb +50 -0
- data/lib/rr/double_definitions/strategies/scope/scope_strategy.rb +15 -0
- data/lib/rr/double_definitions/strategies/strategy.rb +70 -0
- data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +34 -0
- data/lib/rr/double_definitions/strategies/verification/mock.rb +44 -0
- data/lib/rr/double_definitions/strategies/verification/stub.rb +45 -0
- data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +15 -0
- data/lib/rr/double_injection.rb +180 -0
- data/lib/rr/double_matches.rb +51 -0
- data/lib/rr/errors/argument_equality_error.rb +6 -0
- data/lib/rr/errors/double_definition_error.rb +6 -0
- data/lib/rr/errors/double_not_found_error.rb +6 -0
- data/lib/rr/errors/double_order_error.rb +6 -0
- data/lib/rr/errors/rr_error.rb +20 -0
- data/lib/rr/errors/spy_verification_errors/double_injection_not_found_error.rb +8 -0
- data/lib/rr/errors/spy_verification_errors/invocation_count_error.rb +8 -0
- data/lib/rr/errors/spy_verification_errors/spy_verification_error.rb +8 -0
- data/lib/rr/errors/subject_does_not_implement_method_error.rb +6 -0
- data/lib/rr/errors/subject_has_different_arity_error.rb +6 -0
- data/lib/rr/errors/times_called_error.rb +6 -0
- data/lib/rr/expectations/any_argument_expectation.rb +21 -0
- data/lib/rr/expectations/argument_equality_expectation.rb +41 -0
- data/lib/rr/expectations/times_called_expectation.rb +57 -0
- data/lib/rr/hash_with_object_id_key.rb +44 -0
- data/lib/rr/method_dispatches/base_method_dispatch.rb +108 -0
- data/lib/rr/method_dispatches/method_dispatch.rb +61 -0
- data/lib/rr/method_dispatches/method_missing_dispatch.rb +49 -0
- data/lib/rr/proc_from_block.rb +7 -0
- data/lib/rr/recorded_calls.rb +103 -0
- data/lib/rr/space.rb +123 -0
- data/lib/rr/spy_verification.rb +48 -0
- data/lib/rr/spy_verification_proxy.rb +18 -0
- data/lib/rr/times_called_matchers/any_times_matcher.rb +18 -0
- data/lib/rr/times_called_matchers/at_least_matcher.rb +15 -0
- data/lib/rr/times_called_matchers/at_most_matcher.rb +23 -0
- data/lib/rr/times_called_matchers/integer_matcher.rb +19 -0
- data/lib/rr/times_called_matchers/non_terminal.rb +27 -0
- data/lib/rr/times_called_matchers/proc_matcher.rb +11 -0
- data/lib/rr/times_called_matchers/range_matcher.rb +21 -0
- data/lib/rr/times_called_matchers/terminal.rb +20 -0
- data/lib/rr/times_called_matchers/times_called_matcher.rb +44 -0
- data/lib/rr/wildcard_matchers.rb +158 -0
- data/lib/rr/wildcard_matchers/anything.rb +18 -0
- data/lib/rr/wildcard_matchers/boolean.rb +23 -0
- data/lib/rr/wildcard_matchers/duck_type.rb +32 -0
- data/lib/rr/wildcard_matchers/hash_including.rb +29 -0
- data/lib/rr/wildcard_matchers/is_a.rb +25 -0
- data/lib/rr/wildcard_matchers/numeric.rb +13 -0
- data/lib/rr/wildcard_matchers/range.rb +7 -0
- data/lib/rr/wildcard_matchers/regexp.rb +7 -0
- data/lib/rr/wildcard_matchers/satisfy.rb +26 -0
- data/spec/core_spec_suite.rb +19 -0
- data/spec/environment_fixture_setup.rb +7 -0
- data/spec/high_level_spec.rb +398 -0
- data/spec/proc_from_block_spec.rb +14 -0
- data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +67 -0
- data/spec/rr/adapters/rr_methods_creator_spec.rb +149 -0
- data/spec/rr/adapters/rr_methods_space_spec.rb +115 -0
- data/spec/rr/adapters/rr_methods_spec_helper.rb +11 -0
- data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +17 -0
- data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +112 -0
- data/spec/rr/double_definitions/double_definition_creator_proxy_spec.rb +155 -0
- data/spec/rr/double_definitions/double_definition_creator_spec.rb +502 -0
- data/spec/rr/double_definitions/double_definition_spec.rb +1165 -0
- data/spec/rr/double_injection/double_injection_spec.rb +339 -0
- data/spec/rr/double_injection/double_injection_verify_spec.rb +29 -0
- data/spec/rr/double_spec.rb +352 -0
- data/spec/rr/errors/rr_error_spec.rb +67 -0
- data/spec/rr/expectations/any_argument_expectation_spec.rb +47 -0
- data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +14 -0
- data/spec/rr/expectations/argument_equality_expectation_spec.rb +135 -0
- data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +34 -0
- data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +82 -0
- data/spec/rr/expectations/hash_including_spec.rb +17 -0
- data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +59 -0
- data/spec/rr/expectations/satisfy_spec.rb +14 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +46 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +69 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +71 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +23 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +104 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +81 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +83 -0
- data/spec/rr/expectations/times_called_expectation/times_called_expectation_spec.rb +38 -0
- data/spec/rr/rspec/invocation_matcher_spec.rb +279 -0
- data/spec/rr/rspec/rspec_adapter_spec.rb +66 -0
- data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +31 -0
- data/spec/rr/rspec/rspec_backtrace_tweaking_spec_fixture.rb +11 -0
- data/spec/rr/rspec/rspec_usage_spec.rb +86 -0
- data/spec/rr/space/hash_with_object_id_key_spec.rb +88 -0
- data/spec/rr/space/space_spec.rb +550 -0
- data/spec/rr/test_unit/test_helper.rb +7 -0
- data/spec/rr/test_unit/test_unit_backtrace_test.rb +36 -0
- data/spec/rr/test_unit/test_unit_integration_test.rb +57 -0
- data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +47 -0
- data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +55 -0
- data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +70 -0
- data/spec/rr/times_called_matchers/integer_matcher_spec.rb +70 -0
- data/spec/rr/times_called_matchers/proc_matcher_spec.rb +55 -0
- data/spec/rr/times_called_matchers/range_matcher_spec.rb +76 -0
- data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +118 -0
- data/spec/rr/wildcard_matchers/anything_spec.rb +24 -0
- data/spec/rr/wildcard_matchers/boolean_spec.rb +36 -0
- data/spec/rr/wildcard_matchers/duck_type_spec.rb +52 -0
- data/spec/rr/wildcard_matchers/is_a_spec.rb +32 -0
- data/spec/rr/wildcard_matchers/numeric_spec.rb +32 -0
- data/spec/rr/wildcard_matchers/range_spec.rb +35 -0
- data/spec/rr/wildcard_matchers/regexp_spec.rb +43 -0
- data/spec/rr_spec.rb +28 -0
- data/spec/rspec_spec_suite.rb +17 -0
- data/spec/spec_helper.rb +109 -0
- data/spec/spec_suite.rb +31 -0
- data/spec/spy_verification_spec.rb +129 -0
- data/spec/test_unit_spec_suite.rb +21 -0
- metadata +193 -0
@@ -0,0 +1,339 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
|
2
|
+
|
3
|
+
module RR
|
4
|
+
describe DoubleInjection do
|
5
|
+
attr_reader :subject, :method_name, :double_injection
|
6
|
+
macro("sets up subject and method_name") do
|
7
|
+
it "sets up subject and method_name" do
|
8
|
+
double_injection.subject.should === subject
|
9
|
+
double_injection.method_name.should == method_name.to_sym
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "mock/stub" do
|
14
|
+
context "when the subject responds to the injected method" do
|
15
|
+
before do
|
16
|
+
@subject = Object.new
|
17
|
+
class << subject
|
18
|
+
attr_reader :original_foobar_called
|
19
|
+
|
20
|
+
def foobar
|
21
|
+
@original_foobar_called = true
|
22
|
+
:original_foobar
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def subject.foobar
|
27
|
+
:original_foobar
|
28
|
+
end
|
29
|
+
|
30
|
+
subject.should respond_to(:foobar)
|
31
|
+
subject.methods.should include('foobar')
|
32
|
+
stub(subject).foobar {:new_foobar}
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "being bound" do
|
36
|
+
it "sets __rr__original_{method_name} to the original method" do
|
37
|
+
subject.__rr__original_foobar.should == :original_foobar
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "being called" do
|
41
|
+
it "returns the return value of the block" do
|
42
|
+
subject.foobar.should == :new_foobar
|
43
|
+
end
|
44
|
+
|
45
|
+
it "does not call the original method" do
|
46
|
+
subject.foobar
|
47
|
+
subject.original_foobar_called.should be_nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "being reset" do
|
52
|
+
before do
|
53
|
+
RR::Space.reset_double(subject, :foobar)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "rebinds the original method" do
|
57
|
+
subject.foobar.should == :original_foobar
|
58
|
+
end
|
59
|
+
|
60
|
+
it "removes __rr__original_{method_name}" do
|
61
|
+
subject.should_not respond_to(:__rr__original_foobar)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when the subject does not respond to the injected method" do
|
68
|
+
before do
|
69
|
+
@subject = Object.new
|
70
|
+
subject.should_not respond_to(:foobar)
|
71
|
+
subject.methods.should_not include('foobar')
|
72
|
+
stub(subject).foobar {:new_foobar}
|
73
|
+
end
|
74
|
+
|
75
|
+
it "does not set __rr__original_{method_name} to the original method" do
|
76
|
+
subject.should_not respond_to(:__rr__original_foobar)
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "being called" do
|
80
|
+
it "calls the newly defined method" do
|
81
|
+
subject.foobar.should == :new_foobar
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "being reset" do
|
86
|
+
before do
|
87
|
+
RR::Space.reset_double(subject, :foobar)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "unsets the foobar method" do
|
91
|
+
subject.should_not respond_to(:foobar)
|
92
|
+
subject.methods.should_not include('foobar')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "mock/stub + proxy" do
|
99
|
+
context "when the subject responds to the injected method" do
|
100
|
+
context "when the subject has the method defined" do
|
101
|
+
describe "being bound" do
|
102
|
+
before do
|
103
|
+
@subject = Object.new
|
104
|
+
|
105
|
+
def subject.foobar
|
106
|
+
:original_foobar
|
107
|
+
end
|
108
|
+
|
109
|
+
subject.should respond_to(:foobar)
|
110
|
+
subject.methods.should include('foobar')
|
111
|
+
stub.proxy(subject).foobar {:new_foobar}
|
112
|
+
end
|
113
|
+
|
114
|
+
it "aliases the original method to __rr__original_{method_name}" do
|
115
|
+
subject.__rr__original_foobar.should == :original_foobar
|
116
|
+
end
|
117
|
+
|
118
|
+
it "replaces the original method with the new method" do
|
119
|
+
subject.foobar.should == :new_foobar
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "being called" do
|
123
|
+
it "calls the original method first and sends it into the block" do
|
124
|
+
original_return_value = nil
|
125
|
+
stub.proxy(subject).foobar {|original_return_value| :new_foobar}
|
126
|
+
subject.foobar.should == :new_foobar
|
127
|
+
original_return_value.should == :original_foobar
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "being reset" do
|
132
|
+
before do
|
133
|
+
RR::Space.reset_double(subject, :foobar)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "rebinds the original method" do
|
137
|
+
subject.foobar.should == :original_foobar
|
138
|
+
end
|
139
|
+
|
140
|
+
it "removes __rr__original_{method_name}" do
|
141
|
+
subject.should_not respond_to(:__rr__original_foobar)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context "when the subject does not have the method defined" do
|
148
|
+
describe "being bound" do
|
149
|
+
before do
|
150
|
+
@subject = Object.new
|
151
|
+
setup_subject
|
152
|
+
|
153
|
+
subject.should respond_to(:foobar)
|
154
|
+
stub.proxy(subject).foobar {:new_foobar}
|
155
|
+
end
|
156
|
+
|
157
|
+
def setup_subject
|
158
|
+
def subject.respond_to?(method_name)
|
159
|
+
if method_name.to_sym == :foobar
|
160
|
+
true
|
161
|
+
else
|
162
|
+
super
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
it "does not define __rr__original_{method_name}" do
|
168
|
+
subject.methods.should_not include("__rr__original_foobar")
|
169
|
+
end
|
170
|
+
|
171
|
+
context "when method is defined after being bound and before being called" do
|
172
|
+
def setup_subject
|
173
|
+
super
|
174
|
+
def subject.foobar
|
175
|
+
:original_foobar
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
describe "being called" do
|
180
|
+
it "defines __rr__original_{method_name} to be the lazily created method" do
|
181
|
+
subject.methods.should include("__rr__original_foobar")
|
182
|
+
subject.__rr__original_foobar.should == :original_foobar
|
183
|
+
end
|
184
|
+
|
185
|
+
it "calls the original method first and sends it into the block" do
|
186
|
+
original_return_value = nil
|
187
|
+
stub.proxy(subject).foobar {|original_return_value| :new_foobar}
|
188
|
+
subject.foobar.should == :new_foobar
|
189
|
+
original_return_value.should == :original_foobar
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "being reset" do
|
194
|
+
before do
|
195
|
+
RR::Space.reset_double(subject, :foobar)
|
196
|
+
end
|
197
|
+
|
198
|
+
it "rebinds the original method" do
|
199
|
+
subject.foobar.should == :original_foobar
|
200
|
+
end
|
201
|
+
|
202
|
+
it "removes __rr__original_{method_name}" do
|
203
|
+
subject.should_not respond_to(:__rr__original_foobar)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context "when method is still not defined" do
|
209
|
+
context "when the method is lazily created" do
|
210
|
+
def setup_subject
|
211
|
+
super
|
212
|
+
def subject.method_missing(method_name, *args, &block)
|
213
|
+
if method_name.to_sym == :foobar
|
214
|
+
def self.foobar
|
215
|
+
:original_foobar
|
216
|
+
end
|
217
|
+
|
218
|
+
foobar
|
219
|
+
else
|
220
|
+
super
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
describe "being called" do
|
226
|
+
it "defines __rr__original_{method_name} to be the lazily created method" do
|
227
|
+
subject.foobar
|
228
|
+
subject.methods.should include("__rr__original_foobar")
|
229
|
+
subject.__rr__original_foobar.should == :original_foobar
|
230
|
+
end
|
231
|
+
|
232
|
+
it "calls the lazily created method and returns the injected method return value" do
|
233
|
+
original_return_value = nil
|
234
|
+
stub.proxy(subject).foobar {|original_return_value| :new_foobar}
|
235
|
+
subject.foobar.should == :new_foobar
|
236
|
+
original_return_value.should == :original_foobar
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
describe "being reset" do
|
241
|
+
context "when reset before being called" do
|
242
|
+
before do
|
243
|
+
RR::Space.reset_double(subject, :foobar)
|
244
|
+
end
|
245
|
+
|
246
|
+
it "rebinds the original method" do
|
247
|
+
subject.foobar.should == :original_foobar
|
248
|
+
end
|
249
|
+
|
250
|
+
it "removes __rr__original_{method_name}" do
|
251
|
+
subject.should_not respond_to(:__rr__original_foobar)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
context "when the method is not lazily created (handled in method_missing)" do
|
258
|
+
def setup_subject
|
259
|
+
super
|
260
|
+
def subject.method_missing(method_name, *args, &block)
|
261
|
+
if method_name.to_sym == :foobar
|
262
|
+
:original_foobar
|
263
|
+
else
|
264
|
+
super
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
describe "being called" do
|
270
|
+
it "does not define the __rr__original_{method_name}" do
|
271
|
+
subject.foobar
|
272
|
+
subject.methods.should_not include("__rr__original_foobar")
|
273
|
+
end
|
274
|
+
|
275
|
+
it "calls the lazily created method and returns the injected method return value" do
|
276
|
+
original_return_value = nil
|
277
|
+
stub.proxy(subject).foobar {|original_return_value| :new_foobar}
|
278
|
+
subject.foobar.should == :new_foobar
|
279
|
+
original_return_value.should == :original_foobar
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
describe "being reset" do
|
284
|
+
before do
|
285
|
+
RR::Space.reset_double(subject, :foobar)
|
286
|
+
end
|
287
|
+
|
288
|
+
it "rebinds the original method" do
|
289
|
+
subject.foobar.should == :original_foobar
|
290
|
+
end
|
291
|
+
|
292
|
+
it "removes __rr__original_{method_name}" do
|
293
|
+
subject.should_not respond_to(:__rr__original_foobar)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
context "when the subject does not respond to the injected method" do
|
303
|
+
describe "being bound" do
|
304
|
+
before do
|
305
|
+
@subject = Object.new
|
306
|
+
subject.should_not respond_to(:foobar)
|
307
|
+
subject.methods.should_not include('foobar')
|
308
|
+
stub.proxy(subject).foobar {:new_foobar}
|
309
|
+
end
|
310
|
+
|
311
|
+
it "adds the method to the subject" do
|
312
|
+
subject.should respond_to(:foobar)
|
313
|
+
subject.methods.should include('foobar')
|
314
|
+
end
|
315
|
+
|
316
|
+
describe "being called" do
|
317
|
+
it "raises a NoMethodError" do
|
318
|
+
lambda do
|
319
|
+
subject.foobar
|
320
|
+
end.should raise_error(NoMethodError)
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
describe "being reset" do
|
325
|
+
before do
|
326
|
+
RR::Space.reset_double(subject, :foobar)
|
327
|
+
end
|
328
|
+
|
329
|
+
it "unsets the foobar method" do
|
330
|
+
subject.should_not respond_to(:foobar)
|
331
|
+
subject.methods.should_not include('foobar')
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
|
2
|
+
|
3
|
+
module RR
|
4
|
+
module DoubleDefinitions
|
5
|
+
describe DoubleInjection, "#verify" do
|
6
|
+
it_should_behave_like "Swapped Space"
|
7
|
+
attr_reader :space, :subject, :method_name, :double_injection
|
8
|
+
before do
|
9
|
+
@subject = Object.new
|
10
|
+
@method_name = :foobar
|
11
|
+
subject.methods.should_not include(method_name.to_s)
|
12
|
+
@double_injection = space.double_injection(subject, method_name)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "verifies each double was met" do
|
16
|
+
double = Double.new(
|
17
|
+
double_injection,
|
18
|
+
DoubleDefinition.new(DoubleDefinitions::DoubleDefinitionCreator.new, subject)
|
19
|
+
)
|
20
|
+
double_injection.register_double double
|
21
|
+
|
22
|
+
double.definition.with(1).once.returns {nil}
|
23
|
+
lambda {double_injection.verify}.should raise_error(Errors::TimesCalledError)
|
24
|
+
subject.foobar(1)
|
25
|
+
lambda {double_injection.verify}.should_not raise_error
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,352 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
2
|
+
|
3
|
+
module RR
|
4
|
+
describe Double do
|
5
|
+
it_should_behave_like "Swapped Space"
|
6
|
+
attr_reader :subject, :double_injection, :definition, :definition_creator, :double
|
7
|
+
before do
|
8
|
+
@subject = Object.new
|
9
|
+
def subject.foobar(a, b)
|
10
|
+
[b, a]
|
11
|
+
end
|
12
|
+
@double_injection = create_double_injection
|
13
|
+
@definition_creator = DoubleDefinitions::DoubleDefinitionCreator.new
|
14
|
+
@definition = DoubleDefinitions::DoubleDefinition.new(definition_creator, subject).
|
15
|
+
any_number_of_times.
|
16
|
+
with_any_args
|
17
|
+
@double = Double.new(double_injection, definition)
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_double_injection
|
21
|
+
space.double_injection(subject, :foobar)
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#initialize" do
|
25
|
+
it "registers self with associated DoubleInjection" do
|
26
|
+
double_injection.doubles.should include(double)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#ordered?" do
|
31
|
+
it "defaults to false" do
|
32
|
+
double.should_not be_ordered
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#call" do
|
37
|
+
describe "when verbose" do
|
38
|
+
it "prints the message call" do
|
39
|
+
double.definition.verbose
|
40
|
+
output = nil
|
41
|
+
(class << double; self; end).__send__(:define_method, :puts) do |output|
|
42
|
+
output = output
|
43
|
+
end
|
44
|
+
subject.foobar(1, 2)
|
45
|
+
output.should == Double.formatted_name(:foobar, [1, 2])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "when not verbose" do
|
50
|
+
it "does not print the message call" do
|
51
|
+
output = nil
|
52
|
+
(class << double; self; end).__send__(:define_method, :puts) do |output|
|
53
|
+
output = output
|
54
|
+
end
|
55
|
+
subject.foobar(1, 2)
|
56
|
+
output.should be_nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "when implemented by a lambda" do
|
61
|
+
it "calls the return lambda when implemented by a lambda" do
|
62
|
+
double.definition.returns {|arg| "returning #{arg}"}
|
63
|
+
subject.foobar(:foobar).should == "returning foobar"
|
64
|
+
end
|
65
|
+
|
66
|
+
it "calls and returns the after_call when after_call is set" do
|
67
|
+
double.definition.returns {|arg| "returning #{arg}"}.after_call do |value|
|
68
|
+
"#{value} after call"
|
69
|
+
end
|
70
|
+
subject.foobar(:foobar).should == "returning foobar after call"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "returns nil when to returns is not set" do
|
74
|
+
subject.foobar.should be_nil
|
75
|
+
end
|
76
|
+
|
77
|
+
it "works when times_called is not set" do
|
78
|
+
double.definition.returns {:value}
|
79
|
+
subject.foobar
|
80
|
+
end
|
81
|
+
|
82
|
+
it "verifes the times_called does not exceed the TimesCalledExpectation" do
|
83
|
+
double.definition.times(2).returns {:value}
|
84
|
+
|
85
|
+
subject.foobar(:foobar)
|
86
|
+
subject.foobar(:foobar)
|
87
|
+
lambda {subject.foobar(:foobar)}.should raise_error(Errors::TimesCalledError)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "raises DoubleOrderError when ordered and called out of order" do
|
91
|
+
double1 = double
|
92
|
+
double2 = Double.new(double_injection, DoubleDefinitions::DoubleDefinition.new(definition_creator, subject))
|
93
|
+
|
94
|
+
double1.definition.with(1).returns {:return_1}.once.ordered
|
95
|
+
double2.definition.with(2).returns {:return_2}.once.ordered
|
96
|
+
|
97
|
+
lambda do
|
98
|
+
subject.foobar(2)
|
99
|
+
end.should raise_error(
|
100
|
+
Errors::DoubleOrderError,
|
101
|
+
"foobar(2) called out of order in list\n" <<
|
102
|
+
"- foobar(1)\n" <<
|
103
|
+
"- foobar(2)"
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "dispatches to Space#verify_ordered_double when ordered" do
|
108
|
+
verify_ordered_double_called = false
|
109
|
+
passed_in_double = nil
|
110
|
+
space.method(:verify_ordered_double).arity.should == 1
|
111
|
+
(class << space; self; end).class_eval do
|
112
|
+
define_method :verify_ordered_double do |double|
|
113
|
+
passed_in_double = double
|
114
|
+
verify_ordered_double_called = true
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
double.definition.returns {:value}.ordered
|
119
|
+
subject.foobar(:foobar)
|
120
|
+
verify_ordered_double_called.should be_true
|
121
|
+
passed_in_double.should === double
|
122
|
+
end
|
123
|
+
|
124
|
+
it "does not dispatche to Space#verify_ordered_double when not ordered" do
|
125
|
+
verify_ordered_double_called = false
|
126
|
+
space.method(:verify_ordered_double).arity.should == 1
|
127
|
+
(class << space; self; end).class_eval do
|
128
|
+
define_method :verify_ordered_double do |double|
|
129
|
+
verify_ordered_double_called = true
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
double.definition.returns {:value}
|
134
|
+
subject.foobar(:foobar)
|
135
|
+
verify_ordered_double_called.should be_false
|
136
|
+
end
|
137
|
+
|
138
|
+
it "does not add block argument if no block passed in" do
|
139
|
+
double.definition.with(1, 2).returns {|*args| args}
|
140
|
+
|
141
|
+
args = subject.foobar(1, 2)
|
142
|
+
args.should == [1, 2]
|
143
|
+
end
|
144
|
+
|
145
|
+
it "makes the block the last argument" do
|
146
|
+
double.definition.with(1, 2).returns {|a, b, blk| blk}
|
147
|
+
|
148
|
+
block = subject.foobar(1, 2) {|a, b| [b, a]}
|
149
|
+
block.call(3, 4).should == [4, 3]
|
150
|
+
end
|
151
|
+
|
152
|
+
it "raises ArgumentError when yields was called and no block passed in" do
|
153
|
+
double.definition.with(1, 2).yields(55)
|
154
|
+
|
155
|
+
lambda do
|
156
|
+
subject.foobar(1, 2)
|
157
|
+
end.should raise_error(ArgumentError, "A Block must be passed into the method call when using yields")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "when implemented by a method" do
|
162
|
+
it "sends block to the method" do
|
163
|
+
def subject.foobar(a, b)
|
164
|
+
yield(a, b)
|
165
|
+
end
|
166
|
+
|
167
|
+
double.definition.with(1, 2).implemented_by(subject.method(:foobar))
|
168
|
+
|
169
|
+
subject.foobar(1, 2) {|a, b| [b, a]}.should == [2, 1]
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe "#exact_match?" do
|
175
|
+
context "when no expectation is set" do
|
176
|
+
it "raises a DoubleDefinitionError" do
|
177
|
+
double.definition.argument_expectation = nil
|
178
|
+
lambda do
|
179
|
+
double.exact_match?
|
180
|
+
end.should raise_error(Errors::DoubleDefinitionError)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context "when arguments are not an exact match" do
|
185
|
+
it "returns false" do
|
186
|
+
double.definition.with(1, 2, 3)
|
187
|
+
double.should_not be_exact_match(1, 2)
|
188
|
+
double.should_not be_exact_match(1)
|
189
|
+
double.should_not be_exact_match()
|
190
|
+
double.should_not be_exact_match("does not match")
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context "when arguments are an exact match" do
|
195
|
+
it "returns true" do
|
196
|
+
double.definition.with(1, 2, 3)
|
197
|
+
double.should be_exact_match(1, 2, 3)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
describe "#wildcard_match?" do
|
203
|
+
context "when no expectation set" do
|
204
|
+
it "raises a DoubleDefinitionError" do
|
205
|
+
double.definition.argument_expectation = nil
|
206
|
+
lambda do
|
207
|
+
double.wildcard_match?
|
208
|
+
end.should raise_error(Errors::DoubleDefinitionError)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
context "when arguments are an exact match" do
|
213
|
+
it "returns true" do
|
214
|
+
double.definition.with(1, 2, 3)
|
215
|
+
double.should be_wildcard_match(1, 2, 3)
|
216
|
+
double.should_not be_wildcard_match(1, 2)
|
217
|
+
double.should_not be_wildcard_match(1)
|
218
|
+
double.should_not be_wildcard_match()
|
219
|
+
double.should_not be_wildcard_match("does not match")
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
context "when with_any_args" do
|
224
|
+
it "returns true" do
|
225
|
+
double.definition.with_any_args
|
226
|
+
|
227
|
+
double.should be_wildcard_match(1, 2, 3)
|
228
|
+
double.should be_wildcard_match(1, 2)
|
229
|
+
double.should be_wildcard_match(1)
|
230
|
+
double.should be_wildcard_match()
|
231
|
+
double.should be_wildcard_match("does not match")
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
describe "#attempt?" do
|
237
|
+
context "when TimesCalledExpectation#attempt? is true" do
|
238
|
+
it "returns true" do
|
239
|
+
double.definition.with(1, 2, 3).twice
|
240
|
+
subject.foobar(1, 2, 3)
|
241
|
+
double.times_called_expectation.should be_attempt
|
242
|
+
double.should be_attempt
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
context "when TimesCalledExpectation#attempt? is true" do
|
247
|
+
it "returns false" do
|
248
|
+
double.definition.with(1, 2, 3).twice
|
249
|
+
subject.foobar(1, 2, 3)
|
250
|
+
subject.foobar(1, 2, 3)
|
251
|
+
double.times_called_expectation.should_not be_attempt
|
252
|
+
double.should_not be_attempt
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
context "when there is no Times Called expectation" do
|
257
|
+
it "raises a DoubleDefinitionError" do
|
258
|
+
double.definition.with(1, 2, 3)
|
259
|
+
double.definition.times_matcher = nil
|
260
|
+
lambda do
|
261
|
+
double.should be_attempt
|
262
|
+
end.should raise_error(RR::Errors::DoubleDefinitionError)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
describe "#verify" do
|
268
|
+
it "verifies that times called expectation was met" do
|
269
|
+
double.definition.twice.returns {:return_value}
|
270
|
+
|
271
|
+
lambda {double.verify}.should raise_error(Errors::TimesCalledError)
|
272
|
+
subject.foobar
|
273
|
+
lambda {double.verify}.should raise_error(Errors::TimesCalledError)
|
274
|
+
subject.foobar
|
275
|
+
|
276
|
+
lambda {double.verify}.should_not raise_error
|
277
|
+
end
|
278
|
+
|
279
|
+
it "does not raise an error when there is no times called expectation" do
|
280
|
+
lambda {double.verify}.should_not raise_error
|
281
|
+
subject.foobar
|
282
|
+
lambda {double.verify}.should_not raise_error
|
283
|
+
subject.foobar
|
284
|
+
lambda {double.verify}.should_not raise_error
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
describe "#terminal?" do
|
289
|
+
context "when times_called_expectation's terminal? is true" do
|
290
|
+
it "returns true" do
|
291
|
+
double.definition.once
|
292
|
+
double.times_called_expectation.should be_terminal
|
293
|
+
double.should be_terminal
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
context "when times_called_expectation's terminal? is false" do
|
298
|
+
it "returns false" do
|
299
|
+
double.definition.any_number_of_times
|
300
|
+
double.times_called_expectation.should_not be_terminal
|
301
|
+
double.should_not be_terminal
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
context "when there is no times_matcher" do
|
306
|
+
it "raises a DoubleDefinitionError" do
|
307
|
+
double.definition.times_matcher = nil
|
308
|
+
lambda do
|
309
|
+
double.should_not be_terminal
|
310
|
+
end.should raise_error(RR::Errors::DoubleDefinitionError)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
describe "#method_name" do
|
316
|
+
it "returns the DoubleInjection's method_name" do
|
317
|
+
double_injection.method_name.should == :foobar
|
318
|
+
double.method_name.should == :foobar
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
describe "#expected_arguments" do
|
323
|
+
context "when there is an argument expectation" do
|
324
|
+
it "returns argument expectation's expected_arguments" do
|
325
|
+
double.definition.with(1, 2)
|
326
|
+
double.definition.argument_expectation.should_not be_nil
|
327
|
+
double.expected_arguments.should == [1, 2]
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
context "when there is no argument expectation" do
|
332
|
+
it "raises an DoubleDefinitionError" do
|
333
|
+
double.definition.argument_expectation = nil
|
334
|
+
lambda do
|
335
|
+
double.expected_arguments
|
336
|
+
end.should raise_error(Errors::DoubleDefinitionError)
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
describe "#formatted_name" do
|
342
|
+
it "renders the formatted name of the Double with no arguments" do
|
343
|
+
double.formatted_name.should == "foobar()"
|
344
|
+
end
|
345
|
+
|
346
|
+
it "renders the formatted name of the Double with arguments" do
|
347
|
+
double.definition.with(1, 2)
|
348
|
+
double.formatted_name.should == "foobar(1, 2)"
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|