redinger-rr 0.10.3 → 0.10.4

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