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.
Files changed (133) hide show
  1. data/CHANGES +221 -0
  2. data/README.rdoc +343 -0
  3. data/Rakefile +88 -0
  4. data/VERSION.yml +4 -0
  5. data/lib/rr.rb +88 -0
  6. data/lib/rr/adapters/rr_methods.rb +122 -0
  7. data/lib/rr/adapters/rspec.rb +59 -0
  8. data/lib/rr/adapters/test_unit.rb +29 -0
  9. data/lib/rr/double.rb +152 -0
  10. data/lib/rr/double_definitions/child_double_definition_creator.rb +27 -0
  11. data/lib/rr/double_definitions/double_definition.rb +348 -0
  12. data/lib/rr/double_definitions/double_definition_creator.rb +167 -0
  13. data/lib/rr/double_definitions/double_definition_creator_proxy.rb +37 -0
  14. data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +15 -0
  15. data/lib/rr/double_definitions/strategies/implementation/proxy.rb +62 -0
  16. data/lib/rr/double_definitions/strategies/implementation/reimplementation.rb +14 -0
  17. data/lib/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation.rb +17 -0
  18. data/lib/rr/double_definitions/strategies/scope/instance.rb +15 -0
  19. data/lib/rr/double_definitions/strategies/scope/instance_of_class.rb +50 -0
  20. data/lib/rr/double_definitions/strategies/scope/scope_strategy.rb +15 -0
  21. data/lib/rr/double_definitions/strategies/strategy.rb +70 -0
  22. data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +34 -0
  23. data/lib/rr/double_definitions/strategies/verification/mock.rb +44 -0
  24. data/lib/rr/double_definitions/strategies/verification/stub.rb +45 -0
  25. data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +15 -0
  26. data/lib/rr/double_injection.rb +180 -0
  27. data/lib/rr/double_matches.rb +51 -0
  28. data/lib/rr/errors/argument_equality_error.rb +6 -0
  29. data/lib/rr/errors/double_definition_error.rb +6 -0
  30. data/lib/rr/errors/double_not_found_error.rb +6 -0
  31. data/lib/rr/errors/double_order_error.rb +6 -0
  32. data/lib/rr/errors/rr_error.rb +20 -0
  33. data/lib/rr/errors/spy_verification_errors/double_injection_not_found_error.rb +8 -0
  34. data/lib/rr/errors/spy_verification_errors/invocation_count_error.rb +8 -0
  35. data/lib/rr/errors/spy_verification_errors/spy_verification_error.rb +8 -0
  36. data/lib/rr/errors/subject_does_not_implement_method_error.rb +6 -0
  37. data/lib/rr/errors/subject_has_different_arity_error.rb +6 -0
  38. data/lib/rr/errors/times_called_error.rb +6 -0
  39. data/lib/rr/expectations/any_argument_expectation.rb +21 -0
  40. data/lib/rr/expectations/argument_equality_expectation.rb +41 -0
  41. data/lib/rr/expectations/times_called_expectation.rb +57 -0
  42. data/lib/rr/hash_with_object_id_key.rb +44 -0
  43. data/lib/rr/method_dispatches/base_method_dispatch.rb +108 -0
  44. data/lib/rr/method_dispatches/method_dispatch.rb +61 -0
  45. data/lib/rr/method_dispatches/method_missing_dispatch.rb +49 -0
  46. data/lib/rr/proc_from_block.rb +7 -0
  47. data/lib/rr/recorded_calls.rb +103 -0
  48. data/lib/rr/space.rb +123 -0
  49. data/lib/rr/spy_verification.rb +48 -0
  50. data/lib/rr/spy_verification_proxy.rb +18 -0
  51. data/lib/rr/times_called_matchers/any_times_matcher.rb +18 -0
  52. data/lib/rr/times_called_matchers/at_least_matcher.rb +15 -0
  53. data/lib/rr/times_called_matchers/at_most_matcher.rb +23 -0
  54. data/lib/rr/times_called_matchers/integer_matcher.rb +19 -0
  55. data/lib/rr/times_called_matchers/non_terminal.rb +27 -0
  56. data/lib/rr/times_called_matchers/proc_matcher.rb +11 -0
  57. data/lib/rr/times_called_matchers/range_matcher.rb +21 -0
  58. data/lib/rr/times_called_matchers/terminal.rb +20 -0
  59. data/lib/rr/times_called_matchers/times_called_matcher.rb +44 -0
  60. data/lib/rr/wildcard_matchers.rb +158 -0
  61. data/lib/rr/wildcard_matchers/anything.rb +18 -0
  62. data/lib/rr/wildcard_matchers/boolean.rb +23 -0
  63. data/lib/rr/wildcard_matchers/duck_type.rb +32 -0
  64. data/lib/rr/wildcard_matchers/hash_including.rb +29 -0
  65. data/lib/rr/wildcard_matchers/is_a.rb +25 -0
  66. data/lib/rr/wildcard_matchers/numeric.rb +13 -0
  67. data/lib/rr/wildcard_matchers/range.rb +7 -0
  68. data/lib/rr/wildcard_matchers/regexp.rb +7 -0
  69. data/lib/rr/wildcard_matchers/satisfy.rb +26 -0
  70. data/spec/core_spec_suite.rb +19 -0
  71. data/spec/environment_fixture_setup.rb +7 -0
  72. data/spec/high_level_spec.rb +398 -0
  73. data/spec/proc_from_block_spec.rb +14 -0
  74. data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +67 -0
  75. data/spec/rr/adapters/rr_methods_creator_spec.rb +149 -0
  76. data/spec/rr/adapters/rr_methods_space_spec.rb +115 -0
  77. data/spec/rr/adapters/rr_methods_spec_helper.rb +11 -0
  78. data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +17 -0
  79. data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +112 -0
  80. data/spec/rr/double_definitions/double_definition_creator_proxy_spec.rb +155 -0
  81. data/spec/rr/double_definitions/double_definition_creator_spec.rb +502 -0
  82. data/spec/rr/double_definitions/double_definition_spec.rb +1165 -0
  83. data/spec/rr/double_injection/double_injection_spec.rb +339 -0
  84. data/spec/rr/double_injection/double_injection_verify_spec.rb +29 -0
  85. data/spec/rr/double_spec.rb +352 -0
  86. data/spec/rr/errors/rr_error_spec.rb +67 -0
  87. data/spec/rr/expectations/any_argument_expectation_spec.rb +47 -0
  88. data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +14 -0
  89. data/spec/rr/expectations/argument_equality_expectation_spec.rb +135 -0
  90. data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +34 -0
  91. data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +82 -0
  92. data/spec/rr/expectations/hash_including_spec.rb +17 -0
  93. data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +59 -0
  94. data/spec/rr/expectations/satisfy_spec.rb +14 -0
  95. data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +46 -0
  96. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +69 -0
  97. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +71 -0
  98. data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +23 -0
  99. data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +104 -0
  100. data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +81 -0
  101. data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +83 -0
  102. data/spec/rr/expectations/times_called_expectation/times_called_expectation_spec.rb +38 -0
  103. data/spec/rr/rspec/invocation_matcher_spec.rb +279 -0
  104. data/spec/rr/rspec/rspec_adapter_spec.rb +66 -0
  105. data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +31 -0
  106. data/spec/rr/rspec/rspec_backtrace_tweaking_spec_fixture.rb +11 -0
  107. data/spec/rr/rspec/rspec_usage_spec.rb +86 -0
  108. data/spec/rr/space/hash_with_object_id_key_spec.rb +88 -0
  109. data/spec/rr/space/space_spec.rb +550 -0
  110. data/spec/rr/test_unit/test_helper.rb +7 -0
  111. data/spec/rr/test_unit/test_unit_backtrace_test.rb +36 -0
  112. data/spec/rr/test_unit/test_unit_integration_test.rb +57 -0
  113. data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +47 -0
  114. data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +55 -0
  115. data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +70 -0
  116. data/spec/rr/times_called_matchers/integer_matcher_spec.rb +70 -0
  117. data/spec/rr/times_called_matchers/proc_matcher_spec.rb +55 -0
  118. data/spec/rr/times_called_matchers/range_matcher_spec.rb +76 -0
  119. data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +118 -0
  120. data/spec/rr/wildcard_matchers/anything_spec.rb +24 -0
  121. data/spec/rr/wildcard_matchers/boolean_spec.rb +36 -0
  122. data/spec/rr/wildcard_matchers/duck_type_spec.rb +52 -0
  123. data/spec/rr/wildcard_matchers/is_a_spec.rb +32 -0
  124. data/spec/rr/wildcard_matchers/numeric_spec.rb +32 -0
  125. data/spec/rr/wildcard_matchers/range_spec.rb +35 -0
  126. data/spec/rr/wildcard_matchers/regexp_spec.rb +43 -0
  127. data/spec/rr_spec.rb +28 -0
  128. data/spec/rspec_spec_suite.rb +17 -0
  129. data/spec/spec_helper.rb +109 -0
  130. data/spec/spec_suite.rb +31 -0
  131. data/spec/spy_verification_spec.rb +129 -0
  132. data/spec/test_unit_spec_suite.rb +21 -0
  133. 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