surrogate 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Readme.md CHANGED
@@ -1,3 +1,5 @@
1
+ Explanation and examples coming soon.
2
+
1
3
  TODO
2
4
  ----
3
5
 
@@ -112,9 +112,9 @@ class Surrogate
112
112
  Set.new surrogate.singleton_class.api_method_names
113
113
  end
114
114
 
115
- # should have new
115
+ # should have new and clone (don't screw up substitutability because of how we implement these)
116
116
  def class_inherited_methods
117
- Set.new surrogate.singleton_class.instance_methods - surrogate.singleton_class.instance_methods(false) + [:new]
117
+ Set.new surrogate.singleton_class.instance_methods - surrogate.singleton_class.instance_methods(false)
118
118
  end
119
119
 
120
120
  # should not have new
@@ -1,6 +1,8 @@
1
1
  class Surrogate
2
2
 
3
3
  # adds surrogate behaviour to your class / singleton class / instances
4
+ #
5
+ # please refactor me!
4
6
  class Endower
5
7
  def self.endow(klass, &playlist)
6
8
  new(klass, &playlist).endow
@@ -60,19 +62,22 @@ class Surrogate
60
62
  end
61
63
 
62
64
  def can_get_a_new(klass)
63
- klass.define_singleton_method :reprise do
64
- new_klass = Class.new self
65
- surrogate = @surrogate
66
- Surrogate.endow new_klass do
67
- surrogate.api_methods.each do |method_name, options|
68
- define method_name, options.to_hash, &options.default_proc
65
+ klass.extend Module.new {
66
+ # use a module so that the method is inherited (important for substitutability)
67
+ def clone
68
+ new_klass = Class.new self
69
+ surrogate = @surrogate
70
+ Surrogate.endow new_klass do
71
+ surrogate.api_methods.each do |method_name, options|
72
+ define method_name, options.to_hash, &options.default_proc
73
+ end
69
74
  end
75
+ @hatchery.api_methods.each do |method_name, options|
76
+ new_klass.define method_name, options.to_hash, &options.default_proc
77
+ end
78
+ new_klass
70
79
  end
71
- @hatchery.api_methods.each do |method_name, options|
72
- new_klass.define method_name, options.to_hash, &options.default_proc
73
- end
74
- new_klass
75
- end
80
+ }
76
81
  end
77
82
 
78
83
  def remember_invocations_for_instances_of(klass)
@@ -86,13 +91,16 @@ class Surrogate
86
91
  end
87
92
 
88
93
  def hijack_instantiation_of(klass)
89
- def klass.new(*args)
90
- instance = allocate
91
- hatchery = @hatchery
92
- instance.instance_eval { @surrogate = Hatchling.new instance, hatchery }
93
- instance.send :initialize, *args
94
- instance
95
- end
94
+ # use a module so that the method is inherited (important for substitutability)
95
+ klass.extend Module.new {
96
+ def new(*args)
97
+ instance = allocate
98
+ hatchery = @hatchery
99
+ instance.instance_eval { @surrogate = Hatchling.new instance, hatchery }
100
+ instance.send :initialize, *args
101
+ instance
102
+ end
103
+ }
96
104
  end
97
105
 
98
106
  def enable_defining_methods(klass)
@@ -15,8 +15,14 @@ class Surrogate
15
15
  invoked_methods[method_name] << args
16
16
  return get_default method_name, args unless has_ivar? method_name
17
17
  ivar = get_ivar method_name
18
- return ivar unless ivar.kind_of? MethodQueue
19
- play_from_queue ivar, method_name
18
+ case ivar
19
+ when MethodQueue
20
+ play_from_queue ivar, method_name
21
+ when Exception
22
+ raise ivar
23
+ else
24
+ ivar
25
+ end
20
26
  end
21
27
 
22
28
  def prepare_method(method_name, args, &block)
@@ -4,7 +4,9 @@ class Surrogate
4
4
 
5
5
  def dequeue
6
6
  raise QueueEmpty if empty?
7
- queue.shift
7
+ current = queue.shift
8
+ raise current if current.kind_of? Exception
9
+ current
8
10
  end
9
11
 
10
12
  def empty?
@@ -1,3 +1,3 @@
1
1
  class Surrogate
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -36,7 +36,7 @@ describe Surrogate do
36
36
 
37
37
 
38
38
  # don't affect the real user class
39
- user_class = Mock::User.reprise
39
+ user_class = Mock::User.clone
40
40
 
41
41
 
42
42
  # ===== set a default =====
@@ -53,7 +53,7 @@ describe Surrogate do
53
53
  # might also be nice to provide a way to raise an error
54
54
 
55
55
  # tracking invocations
56
- user_class = Mock::User.reprise
56
+ user_class = Mock::User.clone
57
57
  user_class.should_not have_been_told_to :find
58
58
  user_class.find 12
59
59
  user_class.find 12
@@ -102,6 +102,13 @@ describe Surrogate do
102
102
  # user.phone_numbers.should == [['123', '456-7890']] # <-- should we use a hook, or default block to make this happen?
103
103
 
104
104
 
105
+ # ===== raise errors =====
106
+
107
+ # pass the error as the return value, it will be raised when method is invoked
108
+ error = StandardError.new("some message")
109
+ user.will_add_phone_number error
110
+ expect { user.add_phone_number }.to raise_error StandardError, "some message"
111
+
105
112
  # ===== Substitutability =====
106
113
 
107
114
  # real user is not a suitable substitute if missing methods that mock user has
@@ -9,7 +9,7 @@ describe 'define' do
9
9
  end
10
10
  end
11
11
 
12
- klass1 = pristine_klass.reprise
12
+ klass1 = pristine_klass.clone
13
13
  klass1.should_not have_been_told_to :find
14
14
  klass1.find(1).should == 123
15
15
  klass1.should have_been_told_to(:find).with(1)
@@ -73,6 +73,25 @@ describe 'define' do
73
73
  end
74
74
  end
75
75
  end
76
+
77
+ describe 'when an argument is an error' do
78
+ it 'raises the error on method invocation' do
79
+ mocked_class = Surrogate.endow(Class.new)
80
+ mocked_class.define :connect
81
+ mock = mocked_class.new
82
+ error = StandardError.new("some message")
83
+
84
+ # for single invocation
85
+ mock.will_connect error
86
+ expect { mock.connect }.to raise_error StandardError, "some message"
87
+
88
+ # for queue
89
+ mock.will_connect 1, error, 2
90
+ mock.connect.should == 1
91
+ expect { mock.connect }.to raise_error StandardError, "some message"
92
+ mock.connect.should == 2
93
+ end
94
+ end
76
95
  end
77
96
 
78
97
 
@@ -246,7 +265,7 @@ describe 'define' do
246
265
  end
247
266
 
248
267
 
249
- describe 'reprise' do
268
+ describe 'clone' do
250
269
  it 'a repetition or further performance of the klass' do
251
270
  pristine_klass = Class.new do
252
271
  Surrogate.endow self do
@@ -257,13 +276,13 @@ describe 'define' do
257
276
  define(:repeat) { 321 }
258
277
  end
259
278
 
260
- klass1 = pristine_klass.reprise
279
+ klass1 = pristine_klass.clone
261
280
  klass1.should_not have_been_told_to :find
262
281
  klass1.find(1).should == 123
263
282
  klass1.should have_been_told_to(:find).with(1)
264
283
  klass1.bind.should == 'abc'
265
284
 
266
- klass2 = pristine_klass.reprise
285
+ klass2 = pristine_klass.clone
267
286
  klass2.will_find 456
268
287
  klass2.find(2).should == 456
269
288
  klass1.find.should == 123
@@ -277,9 +296,9 @@ describe 'define' do
277
296
  klass1.new.repeat.should == 321
278
297
  end
279
298
 
280
- it 'is a subclass of the reprised class' do
299
+ it 'is a subclass of the cloned class' do
281
300
  superclass = Surrogate.endow Class.new
282
- superclass.reprise.new.should be_a_kind_of superclass
301
+ superclass.clone.new.should be_a_kind_of superclass
283
302
  end
284
303
  end
285
304
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: surrogate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-04-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70192551591960 !ruby/object:Gem::Requirement
16
+ requirement: &70270582700600 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 2.8.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70192551591960
24
+ version_requirements: *70270582700600
25
25
  description: Framework to aid in handrolling mock/spy objects.
26
26
  email:
27
27
  - josh.cheek@gmail.com