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 +2 -0
- data/lib/surrogate/api_comparer.rb +2 -2
- data/lib/surrogate/endower.rb +26 -18
- data/lib/surrogate/hatchling.rb +8 -2
- data/lib/surrogate/method_queue.rb +3 -1
- data/lib/surrogate/version.rb +1 -1
- data/spec/acceptance_spec.rb +9 -2
- data/spec/defining_api_methods_spec.rb +25 -6
- metadata +3 -3
data/Readme.md
CHANGED
@@ -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)
|
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
|
data/lib/surrogate/endower.rb
CHANGED
@@ -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.
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
surrogate
|
68
|
-
|
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
|
-
|
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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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)
|
data/lib/surrogate/hatchling.rb
CHANGED
@@ -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
|
-
|
19
|
-
|
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)
|
data/lib/surrogate/version.rb
CHANGED
data/spec/acceptance_spec.rb
CHANGED
@@ -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.
|
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.
|
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.
|
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 '
|
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.
|
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.
|
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
|
299
|
+
it 'is a subclass of the cloned class' do
|
281
300
|
superclass = Surrogate.endow Class.new
|
282
|
-
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.
|
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: &
|
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: *
|
24
|
+
version_requirements: *70270582700600
|
25
25
|
description: Framework to aid in handrolling mock/spy objects.
|
26
26
|
email:
|
27
27
|
- josh.cheek@gmail.com
|