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,88 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ module RR
4
+ describe HashWithObjectIdKey do
5
+ describe "#[] and #[]=" do
6
+ it "stores object via object id" do
7
+ hash = HashWithObjectIdKey.new
8
+ array_1 = []
9
+ hash[array_1] = 1
10
+ array_2 = []
11
+ hash[array_2] = 2
12
+
13
+ hash[array_1].should_not == hash[array_2]
14
+ end
15
+
16
+ it "stores the passed in object" do
17
+ hash = HashWithObjectIdKey.new
18
+ obj = Object.new
19
+ hash[obj] = 1
20
+ hash.instance_eval {@keys}.should == {obj.__id__ => obj}
21
+ end
22
+ end
23
+
24
+ describe "#each" do
25
+ it "iterates through the items in the hash" do
26
+ hash = HashWithObjectIdKey.new
27
+ hash['one'] = 1
28
+ hash['two'] = 2
29
+
30
+ keys = []
31
+ values = []
32
+ hash.each do |key, value|
33
+ keys << key
34
+ values << value
35
+ end
36
+
37
+ keys.sort.should == ['one', 'two']
38
+ values.sort.should == [1, 2]
39
+ end
40
+ end
41
+
42
+ describe "#delete" do
43
+ before do
44
+ @hash = HashWithObjectIdKey.new
45
+ @key = Object.new
46
+ @hash[@key] = 1
47
+ end
48
+
49
+ it "removes the object from the hash" do
50
+ @hash.delete(@key)
51
+ @hash[@key].should == {}
52
+ end
53
+
54
+ it "removes the object from the keys hash" do
55
+ @hash.delete(@key)
56
+ @hash.instance_eval {@keys}.should == {}
57
+ end
58
+ end
59
+
60
+ describe "#keys" do
61
+ before do
62
+ @hash = HashWithObjectIdKey.new
63
+ @key = Object.new
64
+ @hash[@key] = 1
65
+ end
66
+
67
+ it "returns an array of the keys" do
68
+ @hash.keys.should == [@key]
69
+ end
70
+ end
71
+
72
+ describe "#include?" do
73
+ before do
74
+ @hash = HashWithObjectIdKey.new
75
+ @key = Object.new
76
+ @hash[@key] = 1
77
+ end
78
+
79
+ it "returns true when the key is in the Hash" do
80
+ @hash.include?(@key).should be_true
81
+ end
82
+
83
+ it "returns false when the key is not in the Hash" do
84
+ @hash.include?(Object.new).should be_false
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,550 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ module RR
4
+ describe Space do
5
+ it_should_behave_like "Swapped Space"
6
+ attr_reader :space, :subject, :method_name, :double_injection
7
+
8
+ before do
9
+ @subject = Object.new
10
+ end
11
+
12
+ describe ".method_missing" do
13
+ it "proxies to a singleton instance of Space" do
14
+ create_double_args = nil
15
+ (class << space; self; end).class_eval do
16
+ define_method :double_injection do |*args|
17
+ create_double_args = args
18
+ end
19
+ end
20
+
21
+ space.double_injection(:foo, :bar)
22
+ create_double_args.should == [:foo, :bar]
23
+ end
24
+ end
25
+
26
+ describe "#record_call" do
27
+ it "should add a call to the list" do
28
+ object = Object.new
29
+ block = lambda {}
30
+ space.record_call(object,:to_s,[], block)
31
+ space.recorded_calls.should == RR::RecordedCalls.new([[object,:to_s,[], block]])
32
+ end
33
+ end
34
+
35
+ describe "#double_injection" do
36
+ context "when existing subject == but not === with the same method name" do
37
+ it "creates a new DoubleInjection" do
38
+ subject_1 = []
39
+ subject_2 = []
40
+ (subject_1 === subject_2).should be_true
41
+ subject_1.__id__.should_not == subject_2.__id__
42
+
43
+ double_1 = space.double_injection(subject_1, :foobar)
44
+ double_2 = space.double_injection(subject_2, :foobar)
45
+
46
+ double_1.should_not == double_2
47
+ end
48
+ end
49
+
50
+ context "when double_injection does not exist" do
51
+ before do
52
+ def subject.foobar(*args)
53
+ :original_foobar
54
+ end
55
+ @method_name = :foobar
56
+ end
57
+
58
+ context "when method_name is a symbol" do
59
+ it "returns double_injection and adds double_injection to double_injection list" do
60
+ @double_injection = space.double_injection(subject, method_name)
61
+ space.double_injection(subject, method_name).should === double_injection
62
+ double_injection.subject.should === subject
63
+ double_injection.method_name.should === method_name
64
+ end
65
+ end
66
+
67
+ context "when method_name is a string" do
68
+ it "returns double_injection and adds double_injection to double_injection list" do
69
+ @double_injection = space.double_injection(subject, 'foobar')
70
+ space.double_injection(subject, method_name).should === double_injection
71
+ double_injection.subject.should === subject
72
+ double_injection.method_name.should === method_name
73
+ end
74
+ end
75
+
76
+ it "overrides the method when passing a block" do
77
+ original_method = subject.method(:foobar)
78
+ double_injection = space.double_injection(subject, method_name)
79
+ subject.method(:foobar).should_not == original_method
80
+ end
81
+ end
82
+
83
+ context "when double_injection exists" do
84
+ before do
85
+ def subject.foobar(*args)
86
+ :original_foobar
87
+ end
88
+ @method_name = :foobar
89
+ end
90
+
91
+ it "returns the existing double_injection" do
92
+ original_foobar_method = subject.method(:foobar)
93
+ @double_injection = space.double_injection(subject, 'foobar')
94
+
95
+ double_injection.subject_has_original_method?.should be_true
96
+
97
+ space.double_injection(subject, 'foobar').should === double_injection
98
+
99
+ double_injection.reset
100
+ subject.foobar.should == :original_foobar
101
+ end
102
+ end
103
+ end
104
+
105
+ describe "#reset" do
106
+ attr_reader :subject_1, :subject_2
107
+ before do
108
+ @subject_1 = Object.new
109
+ @subject_2 = Object.new
110
+ @method_name = :foobar
111
+ end
112
+
113
+ it "should clear the #recorded_calls" do
114
+ object = Object.new
115
+ space.record_call(object,:to_s,[], nil)
116
+
117
+ space.reset
118
+ space.recorded_calls.should == RR::RecordedCalls.new([])
119
+ end
120
+
121
+ it "removes the ordered doubles" do
122
+ double_1 = new_double(
123
+ space.double_injection(subject_1, :foobar1),
124
+ RR::DoubleDefinitions::DoubleDefinition.new(creator = Object.new, subject_1)
125
+ )
126
+ double_2 = new_double(
127
+ space.double_injection(subject_2, :foobar2),
128
+ RR::DoubleDefinitions::DoubleDefinition.new(creator = Object.new, subject_2)
129
+ )
130
+ double_1.definition.ordered
131
+ double_2.definition.ordered
132
+
133
+ space.ordered_doubles.should_not be_empty
134
+
135
+ space.reset
136
+ space.ordered_doubles.should be_empty
137
+ end
138
+
139
+ it "resets all double_injections" do
140
+ double_1 = space.double_injection(subject_1, method_name)
141
+ double_1_reset_call_count = 0
142
+ (
143
+ class << double_1;
144
+ self;
145
+ end).class_eval do
146
+ define_method(:reset) do ||
147
+ double_1_reset_call_count += 1
148
+ end
149
+ end
150
+ double_2 = space.double_injection(subject_2, method_name)
151
+ double_2_reset_call_count = 0
152
+ (
153
+ class << double_2;
154
+ self;
155
+ end).class_eval do
156
+ define_method(:reset) do ||
157
+ double_2_reset_call_count += 1
158
+ end
159
+ end
160
+
161
+ space.reset
162
+ double_1_reset_call_count.should == 1
163
+ double_2_reset_call_count.should == 1
164
+ end
165
+ end
166
+
167
+ describe "#reset_double" do
168
+ before do
169
+ @method_name = :foobar
170
+ def subject.foobar
171
+ end
172
+ end
173
+
174
+ it "resets the double_injections and restores the original method" do
175
+ original_method = subject.method(method_name)
176
+
177
+ @double_injection = space.double_injection(subject, method_name)
178
+ space.double_injections[subject][method_name].should === double_injection
179
+ subject.method(method_name).should_not == original_method
180
+
181
+ space.reset_double(subject, method_name)
182
+ space.double_injections[subject][method_name].should be_nil
183
+ subject.method(method_name).should == original_method
184
+ end
185
+
186
+ context "when it has no double_injections" do
187
+ it "removes the subject from the double_injections map" do
188
+ double_1 = space.double_injection(subject, :foobar1)
189
+ double_2 = space.double_injection(subject, :foobar2)
190
+
191
+ space.double_injections.include?(subject).should == true
192
+ space.double_injections[subject][:foobar1].should_not be_nil
193
+ space.double_injections[subject][:foobar2].should_not be_nil
194
+
195
+ space.reset_double(subject, :foobar1)
196
+ space.double_injections.include?(subject).should == true
197
+ space.double_injections[subject][:foobar1].should be_nil
198
+ space.double_injections[subject][:foobar2].should_not be_nil
199
+
200
+ space.reset_double(subject, :foobar2)
201
+ space.double_injections.include?(subject).should == false
202
+ end
203
+ end
204
+ end
205
+
206
+ describe "#reset_double_injections" do
207
+ attr_reader :subject_1, :subject_2
208
+ before do
209
+ @subject_1 = Object.new
210
+ @subject_2 = Object.new
211
+ @method_name = :foobar
212
+ end
213
+
214
+ it "resets the double_injection and removes it from the double_injections list" do
215
+ double_injection_1 = space.double_injection(subject_1, method_name)
216
+ double_1_reset_call_count = 0
217
+ (class << double_injection_1; self; end).class_eval do
218
+ define_method(:reset) do
219
+ double_1_reset_call_count += 1
220
+ end
221
+ end
222
+ double_injection_2 = space.double_injection(subject_2, method_name)
223
+ double_2_reset_call_count = 0
224
+ (class << double_injection_2; self; end).class_eval do
225
+ define_method(:reset) do
226
+ double_2_reset_call_count += 1
227
+ end
228
+ end
229
+
230
+ space.__send__(:reset_double_injections)
231
+ double_1_reset_call_count.should == 1
232
+ double_2_reset_call_count.should == 1
233
+ end
234
+ end
235
+
236
+ describe "#register_ordered_double" do
237
+ before(:each) do
238
+ @method_name = :foobar
239
+ @double_injection = space.double_injection(subject, method_name)
240
+ end
241
+
242
+ it "adds the ordered double to the ordered_doubles collection" do
243
+ double_1 = new_double
244
+
245
+ space.ordered_doubles.should == []
246
+ space.register_ordered_double double_1
247
+ space.ordered_doubles.should == [double_1]
248
+
249
+ double_2 = new_double
250
+ space.register_ordered_double double_2
251
+ space.ordered_doubles.should == [double_1, double_2]
252
+ end
253
+ end
254
+
255
+ describe "#verify_doubles" do
256
+ attr_reader :subject_1, :subject_2, :subject3, :double_1, :double_2, :double3
257
+ before do
258
+ @subject_1 = Object.new
259
+ @subject_2 = Object.new
260
+ @subject3 = Object.new
261
+ @method_name = :foobar
262
+ @double_1 = space.double_injection(subject_1, method_name)
263
+ @double_2 = space.double_injection(subject_2, method_name)
264
+ @double3 = space.double_injection(subject3, method_name)
265
+ end
266
+
267
+ context "when passed no arguments" do
268
+ it "verifies and deletes the double_injections" do
269
+ double_1_verify_call_count = 0
270
+ double_1_reset_call_count = 0
271
+ (class << double_1; self; end).class_eval do
272
+ define_method(:verify) do
273
+ double_1_verify_call_count += 1
274
+ end
275
+ define_method(:reset) do
276
+ double_1_reset_call_count += 1
277
+ end
278
+ end
279
+
280
+ double_2_verify_call_count = 0
281
+ double_2_reset_call_count = 0
282
+ (class << double_2; self; end).class_eval do
283
+ define_method(:verify) do
284
+ double_2_verify_call_count += 1
285
+ end
286
+ define_method(:reset) do
287
+ double_2_reset_call_count += 1
288
+ end
289
+ end
290
+
291
+ space.verify_doubles
292
+ double_1_verify_call_count.should == 1
293
+ double_2_verify_call_count.should == 1
294
+ double_1_reset_call_count.should == 1
295
+ double_1_reset_call_count.should == 1
296
+ end
297
+ end
298
+
299
+ context "when passed an Object that has at least one DoubleInjection" do
300
+ it "verifies all Doubles injected into the Object" do
301
+ double_1_verify_call_count = 0
302
+ double_1_reset_call_count = 0
303
+ (class << double_1; self; end).class_eval do
304
+ define_method(:verify) do
305
+ double_1_verify_call_count += 1
306
+ end
307
+ define_method(:reset) do
308
+ double_1_reset_call_count += 1
309
+ end
310
+ end
311
+
312
+ double_2_verify_call_count = 0
313
+ double_2_reset_call_count = 0
314
+ (class << double_2; self; end).class_eval do
315
+ define_method(:verify) do
316
+ double_2_verify_call_count += 1
317
+ end
318
+ define_method(:reset) do
319
+ double_2_reset_call_count += 1
320
+ end
321
+ end
322
+
323
+ space.verify_doubles(subject_1)
324
+
325
+ double_1_verify_call_count.should == 1
326
+ double_1_reset_call_count.should == 1
327
+ double_2_verify_call_count.should == 0
328
+ double_2_reset_call_count.should == 0
329
+ end
330
+ end
331
+
332
+ context "when passed multiple Objects with at least one DoubleInjection" do
333
+ it "verifies the Doubles injected into all of the Objects" do
334
+ double_1_verify_call_count = 0
335
+ double_1_reset_call_count = 0
336
+ (class << double_1; self; end).class_eval do
337
+ define_method(:verify) do
338
+ double_1_verify_call_count += 1
339
+ end
340
+ define_method(:reset) do
341
+ double_1_reset_call_count += 1
342
+ end
343
+ end
344
+
345
+ double_2_verify_call_count = 0
346
+ double_2_reset_call_count = 0
347
+ (class << double_2; self; end).class_eval do
348
+ define_method(:verify) do
349
+ double_2_verify_call_count += 1
350
+ end
351
+ define_method(:reset) do
352
+ double_2_reset_call_count += 1
353
+ end
354
+ end
355
+
356
+ double3_verify_call_count = 0
357
+ double3_reset_call_count = 0
358
+ (class << double3; self; end).class_eval do
359
+ define_method(:verify) do
360
+ double3_verify_call_count += 1
361
+ end
362
+ define_method(:reset) do
363
+ double3_reset_call_count += 1
364
+ end
365
+ end
366
+
367
+ space.verify_doubles(subject_1, subject_2)
368
+
369
+ double_1_verify_call_count.should == 1
370
+ double_1_reset_call_count.should == 1
371
+ double_2_verify_call_count.should == 1
372
+ double_2_reset_call_count.should == 1
373
+ double3_verify_call_count.should == 0
374
+ double3_reset_call_count.should == 0
375
+ end
376
+ end
377
+
378
+ context "when passed an subject that does not have a DoubleInjection" do
379
+ it "does not raise an error" do
380
+ double_1_verify_call_count = 0
381
+ double_1_reset_call_count = 0
382
+ (class << double_1; self; end).class_eval do
383
+ define_method(:verify) do
384
+ double_1_verify_call_count += 1
385
+ end
386
+ define_method(:reset) do
387
+ double_1_reset_call_count += 1
388
+ end
389
+ end
390
+
391
+ double_2_verify_call_count = 0
392
+ double_2_reset_call_count = 0
393
+ (class << double_2; self; end).class_eval do
394
+ define_method(:verify) do
395
+ double_2_verify_call_count += 1
396
+ end
397
+ define_method(:reset) do
398
+ double_2_reset_call_count += 1
399
+ end
400
+ end
401
+
402
+ double3_verify_call_count = 0
403
+ double3_reset_call_count = 0
404
+ (class << double3; self; end).class_eval do
405
+ define_method(:verify) do
406
+ double3_verify_call_count += 1
407
+ end
408
+ define_method(:reset) do
409
+ double3_reset_call_count += 1
410
+ end
411
+ end
412
+
413
+ no_double_injection_object = Object.new
414
+ space.verify_doubles(no_double_injection_object)
415
+
416
+ double_1_verify_call_count.should == 0
417
+ double_1_reset_call_count.should == 0
418
+ double_2_verify_call_count.should == 0
419
+ double_2_reset_call_count.should == 0
420
+ double3_verify_call_count.should == 0
421
+ double3_reset_call_count.should == 0
422
+ end
423
+ end
424
+ end
425
+
426
+ describe "#verify_double" do
427
+ before do
428
+ @method_name = :foobar
429
+ def subject.foobar
430
+ end
431
+ end
432
+
433
+ it "verifies and deletes the double_injection" do
434
+ @double_injection = space.double_injection(subject, method_name)
435
+ space.double_injections[subject][method_name].should === double_injection
436
+
437
+ verify_call_count = 0
438
+ (class << double_injection; self; end).class_eval do
439
+ define_method(:verify) do
440
+ verify_call_count += 1
441
+ end
442
+ end
443
+ space.verify_double(subject, method_name)
444
+ verify_call_count.should == 1
445
+
446
+ space.double_injections[subject][method_name].should be_nil
447
+ end
448
+
449
+ context "when verifying the double_injection raises an error" do
450
+ it "deletes the double_injection and restores the original method" do
451
+ original_method = subject.method(method_name)
452
+
453
+ @double_injection = space.double_injection(subject, method_name)
454
+ subject.method(method_name).should_not == original_method
455
+
456
+ space.double_injections[subject][method_name].should === double_injection
457
+
458
+ verify_called = true
459
+ (class << double_injection; self; end).class_eval do
460
+ define_method(:verify) do
461
+ verify_called = true
462
+ raise "An Error"
463
+ end
464
+ end
465
+ lambda {space.verify_double(subject, method_name)}.should raise_error
466
+ verify_called.should be_true
467
+
468
+ space.double_injections[subject][method_name].should be_nil
469
+ subject.method(method_name).should == original_method
470
+ end
471
+ end
472
+ end
473
+
474
+ describe "#verify_ordered_double" do
475
+ before do
476
+ @method_name = :foobar
477
+ @double_injection = space.double_injection(subject, method_name)
478
+ end
479
+
480
+ macro "#verify_ordered_double" do
481
+ it "raises an error when Double is NonTerminal" do
482
+ double = new_double
483
+ space.register_ordered_double(double)
484
+
485
+ double.definition.any_number_of_times
486
+ double.should_not be_terminal
487
+
488
+ lambda do
489
+ space.verify_ordered_double(double)
490
+ end.should raise_error(
491
+ Errors::DoubleOrderError,
492
+ "Ordered Doubles cannot have a NonTerminal TimesCalledExpectation"
493
+ )
494
+ end
495
+ end
496
+
497
+ context "when the passed in double is at the front of the queue" do
498
+ send "#verify_ordered_double"
499
+ it "keeps the double when times called is not verified" do
500
+ double = new_double
501
+ space.register_ordered_double(double)
502
+
503
+ double.definition.twice
504
+ double.should be_attempt
505
+
506
+ space.verify_ordered_double(double)
507
+ space.ordered_doubles.should include(double)
508
+ end
509
+
510
+ context "when Double#attempt? is false" do
511
+ it "removes the double" do
512
+ double = new_double
513
+ space.register_ordered_double(double)
514
+
515
+ double.definition.with(1).once
516
+ subject.foobar(1)
517
+ double.should_not be_attempt
518
+
519
+ space.verify_ordered_double(double)
520
+ space.ordered_doubles.should_not include(double)
521
+ end
522
+ end
523
+ end
524
+
525
+ context "when the passed in double is not at the front of the queue" do
526
+ send "#verify_ordered_double"
527
+ it "raises error" do
528
+ first_double = new_double
529
+ second_double = new_double
530
+
531
+ lambda do
532
+ space.verify_ordered_double(second_double)
533
+ end.should raise_error(
534
+ Errors::DoubleOrderError,
535
+ "foobar() called out of order in list\n" <<
536
+ "- foobar()\n" <<
537
+ "- foobar()"
538
+ )
539
+ end
540
+
541
+ def new_double
542
+ double = super
543
+ double.definition.once
544
+ space.register_ordered_double(double)
545
+ double
546
+ end
547
+ end
548
+ end
549
+ end
550
+ end