redinger-rr 0.10.3 → 0.10.4

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.
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :minor: 10
3
- :patch: 3
3
+ :patch: 4
4
4
  :major: 0
@@ -31,17 +31,35 @@ module RR
31
31
  else
32
32
  me = self
33
33
 
34
- subject_class.__send__(:alias_method, original_method_missing_alias_name, :method_missing)
35
- bind_method_missing
34
+ unless subject.respond_to?(original_method_missing_alias_name)
35
+ unless subject.respond_to?(:method_missing)
36
+ subject_class.class_eval do
37
+ def method_missing(method_name, *args, &block)
38
+ super
39
+ end
40
+ end
41
+ end
42
+ subject_class.__send__(:alias_method, original_method_missing_alias_name, :method_missing)
43
+ bind_method_missing
44
+ end
45
+
46
+ unless subject.respond_to?(original_singleton_method_added_alias_name)
47
+ unless subject.respond_to?(:singleton_method_added)
48
+ subject_class.class_eval do
49
+ def singleton_method_added(method_name)
50
+ super
51
+ end
52
+ end
53
+ end
36
54
 
37
- subject_class.__send__(:alias_method, original_singleton_method_added_alias_name, :singleton_method_added)
38
- subject_class.__send__(:define_method, :singleton_method_added) do |method_name_arg|
39
- if method_name_arg.to_sym == me.method_name.to_sym
40
- me.send(:deferred_bind_method)
55
+ subject_class.__send__(:alias_method, original_singleton_method_added_alias_name, :singleton_method_added)
56
+ subject_class.__send__(:define_method, :singleton_method_added) do |method_name_arg|
57
+ if me.space.double_injection_exists?(me.subject, method_name_arg)
58
+ me.space.double_injection(me.subject, method_name_arg).send(:deferred_bind_method)
59
+ end
60
+ send(me.send(:original_singleton_method_added_alias_name), method_name_arg)
41
61
  end
42
- send(me.send(:original_singleton_method_added_alias_name), method_name_arg)
43
62
  end
44
- @deferred_bind = true
45
63
  end
46
64
  else
47
65
  bind_method
@@ -56,8 +74,8 @@ module RR
56
74
  double.verify
57
75
  end
58
76
  end
59
-
60
77
  # RR::DoubleInjection#reset removes the injected dispatcher method.
78
+
61
79
  # It binds the original method implementation on the subject
62
80
  # if one exists.
63
81
  def reset
@@ -88,7 +106,7 @@ module RR
88
106
  end
89
107
 
90
108
  def reset_singleton_method_added
91
- if @deferred_bind
109
+ if subject.respond_to?(original_singleton_method_added_alias_name)
92
110
  me = self
93
111
  subject_class.class_eval do
94
112
  alias_method :singleton_method_added, me.send(:original_singleton_method_added_alias_name)
@@ -107,7 +125,7 @@ module RR
107
125
  end
108
126
 
109
127
  def dispatch_method_missing(method_name, args, block)
110
- MethodDispatches::MethodMissingDispatch.new(self, method_name, args, block).call
128
+ MethodDispatches::MethodMissingDispatch.new(subject, method_name, args, block).call
111
129
  end
112
130
 
113
131
  def subject_has_original_method?
@@ -123,7 +141,7 @@ module RR
123
141
  end
124
142
 
125
143
  def original_method_missing_alias_name
126
- "__rr__original_method_missing"
144
+ MethodDispatches::MethodMissingDispatch.original_method_missing_alias_name
127
145
  end
128
146
 
129
147
  def subject_has_method_defined?(method_name)
@@ -3,7 +3,7 @@ module RR
3
3
  class BaseMethodDispatch
4
4
  include Space::Reader
5
5
 
6
- attr_reader :double_injection, :args, :block, :double
6
+ attr_reader :args, :block, :double
7
7
 
8
8
  def call
9
9
  raise NotImplementedError
@@ -50,7 +50,7 @@ module RR
50
50
  if implementation_is_original_method?
51
51
  call_original_method
52
52
  else
53
- if implementation
53
+ if defined?(implementation) && implementation
54
54
  if implementation.is_a?(Method)
55
55
  implementation.call(*args, &block)
56
56
  else
@@ -1,6 +1,7 @@
1
1
  module RR
2
2
  module MethodDispatches
3
3
  class MethodDispatch < BaseMethodDispatch
4
+ attr_reader :double_injection
4
5
  def initialize(double_injection, args, block)
5
6
  @double_injection, @args, @block = double_injection, args, block
6
7
  @double = find_double_to_attempt
@@ -1,14 +1,19 @@
1
1
  module RR
2
2
  module MethodDispatches
3
3
  class MethodMissingDispatch < BaseMethodDispatch
4
- attr_reader :method_name
5
- def initialize(double_injection, method_name, args, block)
6
- @double_injection, @args, @block = double_injection, args, block
7
- @method_name = method_name
4
+ class << self
5
+ def original_method_missing_alias_name
6
+ "__rr__original_method_missing"
7
+ end
8
+ end
9
+
10
+ attr_reader :subject, :method_name
11
+ def initialize(subject, method_name, args, block)
12
+ @subject, @method_name, @args, @block = subject, method_name, args, block
8
13
  end
9
14
 
10
15
  def call
11
- if double_injection.method_name == method_name
16
+ if space.double_injection_exists?(subject, method_name)
12
17
  space.record_call(subject, method_name, args, block)
13
18
  @double = find_double_to_attempt
14
19
 
@@ -36,13 +41,12 @@ module RR
36
41
  end
37
42
 
38
43
  protected
39
-
40
- def original_method_missing_alias_name
41
- double_injection.original_method_missing_alias_name
44
+ def double_injection
45
+ space.double_injection(subject, method_name)
42
46
  end
43
47
 
44
- def subject
45
- double_injection.subject
48
+ def original_method_missing_alias_name
49
+ self.class.original_method_missing_alias_name
46
50
  end
47
51
  end
48
52
  end
@@ -93,6 +93,18 @@ module RR
93
93
  end
94
94
  end
95
95
  end
96
+
97
+ context "when the subject redefines respond_to?" do
98
+ it "does not try to call the implementation" do
99
+ class << subject
100
+ def respond_to?(method_symbol, include_private = false)
101
+ method_symbol == :foobar
102
+ end
103
+ end
104
+ mock(@subject).foobar
105
+ @subject.foobar.should == nil
106
+ end
107
+ end
96
108
  end
97
109
 
98
110
  describe "mock/stub + proxy" do
@@ -146,90 +158,44 @@ module RR
146
158
 
147
159
  context "when the subject does not have the method defined" do
148
160
  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
161
+ context "when the subject has not been previously bound to" do
162
+ before do
163
+ @subject = Object.new
164
+ setup_subject
156
165
 
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
166
+ subject.should respond_to(:foobar)
167
+ stub.proxy(subject).foobar {:new_foobar}
164
168
  end
165
- end
166
169
 
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
170
  def setup_subject
173
- super
174
- def subject.foobar
175
- :original_foobar
171
+ def subject.respond_to?(method_name)
172
+ if method_name.to_sym == :foobar
173
+ true
174
+ else
175
+ super
176
+ end
176
177
  end
177
178
  end
178
179
 
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
180
+ it "does not define __rr__original_{method_name}" do
181
+ subject.methods.should_not include("__rr__original_foobar")
191
182
  end
192
183
 
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
184
+ context "when method is defined after being bound and before being called" do
210
185
  def setup_subject
211
186
  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
187
+ def subject.foobar
188
+ :original_foobar
222
189
  end
223
190
  end
224
191
 
225
192
  describe "being called" do
226
193
  it "defines __rr__original_{method_name} to be the lazily created method" do
227
- subject.foobar
228
194
  subject.methods.should include("__rr__original_foobar")
229
195
  subject.__rr__original_foobar.should == :original_foobar
230
196
  end
231
197
 
232
- it "calls the lazily created method and returns the injected method return value" do
198
+ it "calls the original method first and sends it into the block" do
233
199
  original_return_value = nil
234
200
  stub.proxy(subject).foobar {|original_return_value| :new_foobar}
235
201
  subject.foobar.should == :new_foobar
@@ -238,7 +204,96 @@ module RR
238
204
  end
239
205
 
240
206
  describe "being reset" do
241
- context "when reset before being called" do
207
+ before do
208
+ RR::Space.reset_double(subject, :foobar)
209
+ end
210
+
211
+ it "rebinds the original method" do
212
+ subject.foobar.should == :original_foobar
213
+ end
214
+
215
+ it "removes __rr__original_{method_name}" do
216
+ subject.should_not respond_to(:__rr__original_foobar)
217
+ end
218
+ end
219
+ end
220
+
221
+ context "when method is still not defined" do
222
+ context "when the method is lazily created" do
223
+ def setup_subject
224
+ super
225
+ def subject.method_missing(method_name, *args, &block)
226
+ if method_name.to_sym == :foobar
227
+ def self.foobar
228
+ :original_foobar
229
+ end
230
+
231
+ foobar
232
+ else
233
+ super
234
+ end
235
+ end
236
+ end
237
+
238
+ describe "being called" do
239
+ it "defines __rr__original_{method_name} to be the lazily created method" do
240
+ subject.foobar
241
+ subject.methods.should include("__rr__original_foobar")
242
+ subject.__rr__original_foobar.should == :original_foobar
243
+ end
244
+
245
+ it "calls the lazily created method and returns the injected method return value" do
246
+ original_return_value = nil
247
+ stub.proxy(subject).foobar {|original_return_value| :new_foobar}
248
+ subject.foobar.should == :new_foobar
249
+ original_return_value.should == :original_foobar
250
+ end
251
+ end
252
+
253
+ describe "being reset" do
254
+ context "when reset before being called" do
255
+ before do
256
+ RR::Space.reset_double(subject, :foobar)
257
+ end
258
+
259
+ it "rebinds the original method" do
260
+ subject.foobar.should == :original_foobar
261
+ end
262
+
263
+ it "removes __rr__original_{method_name}" do
264
+ subject.should_not respond_to(:__rr__original_foobar)
265
+ end
266
+ end
267
+ end
268
+ end
269
+
270
+ context "when the method is not lazily created (handled in method_missing)" do
271
+ def setup_subject
272
+ super
273
+ def subject.method_missing(method_name, *args, &block)
274
+ if method_name.to_sym == :foobar
275
+ :original_foobar
276
+ else
277
+ super
278
+ end
279
+ end
280
+ end
281
+
282
+ describe "being called" do
283
+ it "does not define the __rr__original_{method_name}" do
284
+ subject.foobar
285
+ subject.methods.should_not include("__rr__original_foobar")
286
+ end
287
+
288
+ it "calls the lazily created method and returns the injected method return value" do
289
+ original_return_value = nil
290
+ stub.proxy(subject).foobar {|original_return_value| :new_foobar}
291
+ subject.foobar.should == :new_foobar
292
+ original_return_value.should == :original_foobar
293
+ end
294
+ end
295
+
296
+ describe "being reset" do
242
297
  before do
243
298
  RR::Space.reset_double(subject, :foobar)
244
299
  end
@@ -253,26 +308,47 @@ module RR
253
308
  end
254
309
  end
255
310
  end
311
+ end
312
+
313
+ context "when the subject has been previously bound to" do
314
+ before do
315
+ @subject = Object.new
316
+ setup_subject
317
+
318
+ subject.should respond_to(:foobar)
319
+ stub.proxy(subject).baz {:new_baz}
320
+ stub.proxy(subject).foobar {:new_foobar}
321
+ end
322
+
323
+ def setup_subject
324
+ def subject.respond_to?(method_name)
325
+ if method_name.to_sym == :foobar || method_name.to_sym == :baz
326
+ true
327
+ else
328
+ super
329
+ end
330
+ end
331
+ end
256
332
 
257
- context "when the method is not lazily created (handled in method_missing)" do
333
+ it "does not define __rr__original_{method_name}" do
334
+ subject.methods.should_not include("__rr__original_foobar")
335
+ end
336
+
337
+ context "when method is defined after being bound and before being called" do
258
338
  def setup_subject
259
339
  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
340
+ def subject.foobar
341
+ :original_foobar
266
342
  end
267
343
  end
268
344
 
269
345
  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")
346
+ it "defines __rr__original_{method_name} to be the lazily created method" do
347
+ subject.methods.should include("__rr__original_foobar")
348
+ subject.__rr__original_foobar.should == :original_foobar
273
349
  end
274
350
 
275
- it "calls the lazily created method and returns the injected method return value" do
351
+ it "calls the original method first and sends it into the block" do
276
352
  original_return_value = nil
277
353
  stub.proxy(subject).foobar {|original_return_value| :new_foobar}
278
354
  subject.foobar.should == :new_foobar
@@ -294,46 +370,183 @@ module RR
294
370
  end
295
371
  end
296
372
  end
373
+
374
+ context "when method is still not defined" do
375
+ context "when the method is lazily created" do
376
+ def setup_subject
377
+ super
378
+ def subject.method_missing(method_name, *args, &block)
379
+ if method_name.to_sym == :foobar
380
+ def self.foobar
381
+ :original_foobar
382
+ end
383
+
384
+ foobar
385
+ else
386
+ super
387
+ end
388
+ end
389
+ end
390
+
391
+ describe "being called" do
392
+ it "defines __rr__original_{method_name} to be the lazily created method" do
393
+ subject.foobar
394
+ subject.methods.should include("__rr__original_foobar")
395
+ subject.__rr__original_foobar.should == :original_foobar
396
+ end
397
+
398
+ it "calls the lazily created method and returns the injected method return value" do
399
+ original_return_value = nil
400
+ stub.proxy(subject).foobar {|original_return_value| :new_foobar}
401
+ subject.foobar.should == :new_foobar
402
+ original_return_value.should == :original_foobar
403
+ end
404
+ end
405
+
406
+ describe "being reset" do
407
+ context "when reset before being called" do
408
+ before do
409
+ RR::Space.reset_double(subject, :foobar)
410
+ end
411
+
412
+ it "rebinds the original method" do
413
+ subject.foobar.should == :original_foobar
414
+ end
415
+
416
+ it "removes __rr__original_{method_name}" do
417
+ subject.should_not respond_to(:__rr__original_foobar)
418
+ end
419
+ end
420
+ end
421
+ end
422
+
423
+ context "when the method is not lazily created (handled in method_missing)" do
424
+ def setup_subject
425
+ super
426
+ def subject.method_missing(method_name, *args, &block)
427
+ if method_name.to_sym == :foobar
428
+ :original_foobar
429
+ else
430
+ super
431
+ end
432
+ end
433
+ end
434
+
435
+ describe "being called" do
436
+ it "does not define the __rr__original_{method_name}" do
437
+ subject.foobar
438
+ subject.methods.should_not include("__rr__original_foobar")
439
+ end
440
+
441
+ it "calls the lazily created method and returns the injected method return value" do
442
+ original_return_value = nil
443
+ stub.proxy(subject).foobar {|original_return_value| :new_foobar}
444
+ subject.foobar.should == :new_foobar
445
+ original_return_value.should == :original_foobar
446
+ end
447
+ end
448
+
449
+ describe "being reset" do
450
+ before do
451
+ RR::Space.reset_double(subject, :foobar)
452
+ end
453
+
454
+ it "rebinds the original method" do
455
+ subject.foobar.should == :original_foobar
456
+ end
457
+
458
+ it "removes __rr__original_{method_name}" do
459
+ subject.should_not respond_to(:__rr__original_foobar)
460
+ end
461
+ end
462
+ end
463
+ end
297
464
  end
298
465
  end
299
466
  end
300
467
  end
301
468
 
302
469
  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
470
+ context "when the subject responds to the method via method_missing" do
471
+ describe "being bound" do
472
+ before do
473
+ @subject = Object.new
474
+ subject.should_not respond_to(:foobar)
475
+ subject.methods.should_not include('foobar')
476
+ class << subject
477
+ def method_missing(method_name, *args, &block)
478
+ if method_name == :foobar
479
+ :original_foobar
480
+ else
481
+ super
482
+ end
483
+ end
484
+ end
485
+ stub.proxy(subject).foobar {:new_foobar}
486
+ end
310
487
 
311
- it "adds the method to the subject" do
312
- subject.should respond_to(:foobar)
313
- subject.methods.should include('foobar')
314
- end
488
+ it "adds the method to the subject" do
489
+ subject.should respond_to(:foobar)
490
+ subject.methods.should include('foobar')
491
+ end
315
492
 
316
- describe "being called" do
317
- it "raises a NoMethodError" do
318
- lambda do
319
- subject.foobar
320
- end.should raise_error(NoMethodError)
493
+ describe "being called" do
494
+ it "calls the original method first and sends it into the block" do
495
+ original_return_value = nil
496
+ stub.proxy(subject).foobar {|original_return_value| :new_foobar}
497
+ subject.foobar.should == :new_foobar
498
+ original_return_value.should == :original_foobar
499
+ end
321
500
  end
322
- end
323
501
 
324
- describe "being reset" do
325
- before do
326
- RR::Space.reset_double(subject, :foobar)
502
+ describe "being reset" do
503
+ before do
504
+ RR::Space.reset_double(subject, :foobar)
505
+ end
506
+
507
+ it "unsets the foobar method" do
508
+ subject.should_not respond_to(:foobar)
509
+ subject.methods.should_not include('foobar')
510
+ end
327
511
  end
512
+ end
513
+ end
328
514
 
329
- it "unsets the foobar method" do
515
+ context "when the subject would raise a NoMethodError when the method is called" do
516
+ describe "being bound" do
517
+ before do
518
+ @subject = Object.new
330
519
  subject.should_not respond_to(:foobar)
331
520
  subject.methods.should_not include('foobar')
521
+ stub.proxy(subject).foobar {:new_foobar}
522
+ end
523
+
524
+ it "adds the method to the subject" do
525
+ subject.should respond_to(:foobar)
526
+ subject.methods.should include('foobar')
527
+ end
528
+
529
+ describe "being called" do
530
+ it "raises a NoMethodError" do
531
+ lambda do
532
+ subject.foobar
533
+ end.should raise_error(NoMethodError)
534
+ end
535
+ end
536
+
537
+ describe "being reset" do
538
+ before do
539
+ RR::Space.reset_double(subject, :foobar)
540
+ end
541
+
542
+ it "unsets the foobar method" do
543
+ subject.should_not respond_to(:foobar)
544
+ subject.methods.should_not include('foobar')
545
+ end
332
546
  end
333
547
  end
334
548
  end
335
549
  end
336
-
337
550
  end
338
551
  end
339
552
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redinger-rr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.3
4
+ version: 0.10.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Takita
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-30 00:00:00 -04:00
12
+ date: 2009-09-19 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -64,10 +64,10 @@ files:
64
64
  - lib/rr/expectations/any_argument_expectation.rb
65
65
  - lib/rr/expectations/argument_equality_expectation.rb
66
66
  - lib/rr/expectations/times_called_expectation.rb
67
+ - lib/rr/hash_with_object_id_key.rb
67
68
  - lib/rr/method_dispatches/base_method_dispatch.rb
68
69
  - lib/rr/method_dispatches/method_dispatch.rb
69
70
  - lib/rr/method_dispatches/method_missing_dispatch.rb
70
- - lib/rr/hash_with_object_id_key.rb
71
71
  - lib/rr/proc_from_block.rb
72
72
  - lib/rr/recorded_calls.rb
73
73
  - lib/rr/space.rb
@@ -155,10 +155,9 @@ files:
155
155
  - spec/spec_suite.rb
156
156
  - spec/spy_verification_spec.rb
157
157
  - spec/test_unit_spec_suite.rb
158
- has_rdoc: true
158
+ has_rdoc: false
159
159
  homepage: http://pivotallabs.com
160
- licenses: []
161
-
160
+ licenses:
162
161
  post_install_message:
163
162
  rdoc_options:
164
163
  - --main
@@ -187,7 +186,7 @@ signing_key:
187
186
  specification_version: 3
188
187
  summary: RR (Double Ruby) is a double framework that features a rich selection of double techniques and a terse syntax. http://xunitpatterns.com/Test%20Double.html
189
188
  test_files:
190
- - spec/spy_verification_spec.rb
191
189
  - spec/high_level_spec.rb
192
- - spec/rr_spec.rb
193
190
  - spec/proc_from_block_spec.rb
191
+ - spec/rr_spec.rb
192
+ - spec/spy_verification_spec.rb