surrogate 0.2.0 → 0.3.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 +40 -1
- data/lib/surrogate/endower.rb +34 -42
- data/lib/surrogate/hatchery.rb +30 -16
- data/lib/surrogate/hatchling.rb +5 -0
- data/lib/surrogate/rspec/api_method_matchers.rb +0 -4
- data/lib/surrogate/rspec/substitutability_matchers.rb +26 -16
- data/lib/surrogate/version.rb +1 -1
- data/spec/defining_api_methods_spec.rb +17 -18
- data/spec/rspec/substitute_for_spec.rb +123 -44
- metadata +4 -4
data/Readme.md
CHANGED
@@ -1,4 +1,43 @@
|
|
1
|
-
Explanation and examples coming soon
|
1
|
+
Explanation and examples coming soon, but here is a simple example I wrote up for a lightning talk:
|
2
|
+
|
3
|
+
```ruby
|
4
|
+
require 'surrogate'
|
5
|
+
require 'surrogate/rspec'
|
6
|
+
|
7
|
+
module Mock
|
8
|
+
class User
|
9
|
+
Surrogate.endow self
|
10
|
+
define(:name) { 'Josh' }
|
11
|
+
define :phone_numbers
|
12
|
+
define :add_phone_number do |area_code, number|
|
13
|
+
@phone_numbers << [area_code, number]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class User
|
19
|
+
def name()end
|
20
|
+
def phone_numbers()end
|
21
|
+
def add_phone_number()end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe do
|
25
|
+
it 'ensures the mock lib looks like real lib' do
|
26
|
+
Mock::User.should substitute_for User
|
27
|
+
end
|
28
|
+
|
29
|
+
let(:user) { Mock::User.new }
|
30
|
+
|
31
|
+
example 'you can tell it how to behave and ask what happened with it' do
|
32
|
+
user.will_have_name "Sally"
|
33
|
+
|
34
|
+
user.should_not have_been_asked_for_its :name
|
35
|
+
user.name.should == "Sally"
|
36
|
+
user.should have_been_asked_for_its :name
|
37
|
+
end
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
2
41
|
|
3
42
|
TODO
|
4
43
|
----
|
data/lib/surrogate/endower.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
class Surrogate
|
2
2
|
|
3
|
-
#
|
3
|
+
# Adds surrogate behaviour to your class / singleton class / instances
|
4
4
|
#
|
5
5
|
# please refactor me!
|
6
6
|
class Endower
|
@@ -22,29 +22,31 @@ class Surrogate
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def endow_klass
|
25
|
-
|
25
|
+
add_hatchery_to klass
|
26
|
+
klass.extend ClassMethods
|
26
27
|
enable_defining_methods klass
|
27
28
|
record_initialization_for_instances_of klass
|
28
29
|
remember_invocations_for_instances_of klass
|
29
30
|
remember_invocations_for_instances_of klass.singleton_class
|
30
|
-
hijack_instantiation_of klass
|
31
|
-
can_get_a_new klass
|
32
31
|
end
|
33
32
|
|
34
33
|
def endow_singleton_class
|
35
|
-
hatchery =
|
34
|
+
hatchery = add_hatchery_to singleton
|
36
35
|
enable_defining_methods singleton
|
37
36
|
singleton.module_eval &playlist if playlist
|
38
|
-
klass.instance_variable_set :@
|
37
|
+
klass.instance_variable_set :@hatchling, Hatchling.new(klass, hatchery)
|
39
38
|
klass
|
40
39
|
end
|
41
40
|
|
42
|
-
# yeesh :(
|
41
|
+
# yeesh :( pretty sure there isn't a better way to do this
|
43
42
|
def record_initialization_for_instances_of(klass)
|
44
43
|
def klass.method_added(meth)
|
45
|
-
return
|
44
|
+
return if meth != :initialize || @hijacking_initialize
|
46
45
|
@hijacking_initialize = true
|
47
46
|
current_initialize = instance_method :initialize
|
47
|
+
|
48
|
+
# `define' records the args while maintaining the old behaviour
|
49
|
+
# we have to do it stupidly like this because there is no to_proc on an unbound method
|
48
50
|
define :initialize do |*args, &block|
|
49
51
|
current_initialize.bind(self).call(*args, &block)
|
50
52
|
end
|
@@ -61,48 +63,16 @@ class Surrogate
|
|
61
63
|
klass.singleton_class
|
62
64
|
end
|
63
65
|
|
64
|
-
def can_get_a_new(klass)
|
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
|
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
|
79
|
-
end
|
80
|
-
}
|
81
|
-
end
|
82
|
-
|
83
66
|
def remember_invocations_for_instances_of(klass)
|
84
67
|
klass.send :define_method, :invocations do |method_name|
|
85
|
-
@
|
68
|
+
@hatchling.invocations method_name
|
86
69
|
end
|
87
70
|
end
|
88
71
|
|
89
|
-
def
|
72
|
+
def add_hatchery_to(klass)
|
90
73
|
klass.instance_variable_set :@hatchery, Surrogate::Hatchery.new(klass)
|
91
74
|
end
|
92
75
|
|
93
|
-
def hijack_instantiation_of(klass)
|
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
|
-
}
|
104
|
-
end
|
105
|
-
|
106
76
|
def enable_defining_methods(klass)
|
107
77
|
def klass.define(method_name, options={}, &block)
|
108
78
|
@hatchery.define method_name, options, block
|
@@ -113,4 +83,26 @@ class Surrogate
|
|
113
83
|
end
|
114
84
|
end
|
115
85
|
end
|
86
|
+
|
87
|
+
|
88
|
+
# use a module so that the method is inherited (important for substitutability)
|
89
|
+
module ClassMethods
|
90
|
+
def clone
|
91
|
+
hatchling, hatchery = @hatchling, @hatchery
|
92
|
+
Class.new self do
|
93
|
+
Surrogate.endow self do
|
94
|
+
hatchling.api_methods.each { |name, options| define name, options.to_hash, &options.default_proc }
|
95
|
+
end
|
96
|
+
hatchery.api_methods.each { |name, options| define name, options.to_hash, &options.default_proc }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Custom new, because user can define initialize, and ivars should be set before it
|
101
|
+
def new(*args)
|
102
|
+
instance = allocate
|
103
|
+
instance.instance_variable_set :@hatchling, Hatchling.new(instance, @hatchery)
|
104
|
+
instance.send :initialize, *args
|
105
|
+
instance
|
106
|
+
end
|
107
|
+
end
|
116
108
|
end
|
data/lib/surrogate/hatchery.rb
CHANGED
@@ -1,19 +1,22 @@
|
|
1
1
|
class Surrogate
|
2
|
+
|
3
|
+
# This manages the definitions that were given to the class
|
4
|
+
# The hatchlings are added to the instances, and they look here
|
5
|
+
# to find out about how their methods are implemented.
|
2
6
|
class Hatchery
|
3
7
|
attr_accessor :klass
|
4
8
|
|
5
9
|
def initialize(klass)
|
6
10
|
self.klass = klass
|
7
|
-
|
8
|
-
end
|
9
|
-
|
10
|
-
def defines_methods
|
11
|
-
klass.singleton_class.send :define_method, :define, &method(:define)
|
11
|
+
klass_can_define_api_methods
|
12
12
|
end
|
13
13
|
|
14
14
|
def define(method_name, options={}, block)
|
15
|
-
|
15
|
+
add_api_method_for method_name
|
16
|
+
add_verb_helpers_for method_name
|
17
|
+
add_noun_helpers_for method_name
|
16
18
|
api_methods[method_name] = Options.new options, block
|
19
|
+
klass
|
17
20
|
end
|
18
21
|
|
19
22
|
def api_methods
|
@@ -24,24 +27,35 @@ class Surrogate
|
|
24
27
|
api_methods.keys - [:initialize]
|
25
28
|
end
|
26
29
|
|
27
|
-
|
28
|
-
|
30
|
+
private
|
31
|
+
|
32
|
+
def klass_can_define_api_methods
|
33
|
+
klass.singleton_class.send :define_method, :define, &method(:define)
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_api_method_for(method_name)
|
29
37
|
klass.send :define_method, method_name do |*args, &block|
|
30
|
-
@
|
38
|
+
@hatchling.invoke_method method_name, args, &block
|
31
39
|
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_verb_helpers_for(method_name)
|
43
|
+
add_helpers_for method_name, "will_#{method_name}"
|
44
|
+
end
|
32
45
|
|
33
|
-
|
34
|
-
|
46
|
+
def add_noun_helpers_for(method_name)
|
47
|
+
add_helpers_for method_name, "will_have_#{method_name}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_helpers_for(method_name, helper_name)
|
51
|
+
klass.send :define_method, helper_name do |*args, &block|
|
35
52
|
if args.size == 1
|
36
|
-
@
|
53
|
+
@hatchling.prepare_method method_name, args, &block
|
37
54
|
else
|
38
|
-
@
|
55
|
+
@hatchling.prepare_method_queue method_name, args, &block
|
39
56
|
end
|
40
57
|
self
|
41
58
|
end
|
42
|
-
|
43
|
-
# nouns
|
44
|
-
klass.send :alias_method, "will_have_#{method_name}", "will_#{method_name}"
|
45
59
|
end
|
46
60
|
end
|
47
61
|
end
|
data/lib/surrogate/hatchling.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
class Surrogate
|
2
2
|
UnknownMethod = Class.new StandardError
|
3
|
+
|
4
|
+
# This contains the unique behaviour for each instance
|
5
|
+
# It handles method invocation and records the appropriate information
|
3
6
|
class Hatchling
|
4
7
|
attr_accessor :instance, :hatchery
|
5
8
|
|
@@ -15,6 +18,8 @@ class Surrogate
|
|
15
18
|
invoked_methods[method_name] << args
|
16
19
|
return get_default method_name, args unless has_ivar? method_name
|
17
20
|
ivar = get_ivar method_name
|
21
|
+
|
22
|
+
# This may soon need classes for each type which know how to invoke themselves
|
18
23
|
case ivar
|
19
24
|
when MethodQueue
|
20
25
|
play_from_queue ivar, method_name
|
@@ -1,24 +1,34 @@
|
|
1
1
|
class Surrogate
|
2
|
-
|
3
|
-
module MessagesFor
|
4
|
-
::RSpec::Matchers.define :substitute_for do |original_class|
|
2
|
+
::RSpec::Matchers.define :substitute_for do |original_class, options={}|
|
5
3
|
|
6
|
-
|
4
|
+
comparison = nil
|
5
|
+
subset_only = options[:subset]
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
match do |mocked_class|
|
8
|
+
comparison = ApiComparer.new(mocked_class, original_class).compare
|
9
|
+
if subset_only
|
10
|
+
(comparison[:instance][:not_on_actual] + comparison[:class][:not_on_actual]).empty?
|
11
|
+
else
|
12
|
+
(comparison[:instance].values + comparison[:class].values).inject(:+).empty?
|
13
|
+
end
|
14
|
+
end
|
12
15
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
+
failure_message_for_should do
|
17
|
+
extra_instance_methods = comparison[:instance][:not_on_actual ].to_a
|
18
|
+
extra_class_methods = comparison[:class ][:not_on_actual ].to_a
|
19
|
+
missing_instance_methods = comparison[:instance][:not_on_surrogate].to_a
|
20
|
+
missing_class_methods = comparison[:class ][:not_on_surrogate].to_a
|
16
21
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
22
|
+
differences = []
|
23
|
+
differences << "has extra instance methods: #{extra_instance_methods.inspect}" if extra_instance_methods.any?
|
24
|
+
differences << "has extra class methods: #{extra_class_methods.inspect}" if extra_class_methods.any?
|
25
|
+
differences << "is missing instance methods: #{missing_instance_methods}" if !subset_only && missing_instance_methods.any?
|
26
|
+
differences << "is missing class methods: #{missing_class_methods}" if !subset_only && missing_class_methods.any?
|
27
|
+
"Was not substitutable because surrogate " << differences.join(', ')
|
28
|
+
end
|
29
|
+
|
30
|
+
failure_message_for_should_not do
|
31
|
+
"Should not have been substitute, but was"
|
21
32
|
end
|
22
33
|
end
|
23
34
|
end
|
24
|
-
|
data/lib/surrogate/version.rb
CHANGED
@@ -193,35 +193,34 @@ describe 'define' do
|
|
193
193
|
specify 'even works with inheritance' do
|
194
194
|
superclass = Class.new
|
195
195
|
superclass.send(:define_method, :initialize) { @a = 1 }
|
196
|
-
subclass = Class.new superclass
|
197
|
-
|
198
|
-
|
199
|
-
mocked_subclass.new.instance_variable_get(:@a).should == 1
|
196
|
+
subclass = Surrogate.endow Class.new superclass
|
197
|
+
subclass.define :abc
|
198
|
+
subclass.new.instance_variable_get(:@a).should == 1
|
200
199
|
end
|
201
200
|
|
202
201
|
context 'when not an api method' do
|
203
202
|
it 'respects arity (this is probably 1.9.3 only)' do
|
204
|
-
expect { mocked_class.new
|
203
|
+
expect { mocked_class.new 1 }.to raise_error ArgumentError, 'wrong number of arguments(1 for 0)'
|
205
204
|
end
|
206
205
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
@a = a
|
206
|
+
describe 'invocations are recorded anyway' do
|
207
|
+
specify 'even when initialize is defined after surrogate block' do
|
208
|
+
klass = Class.new do
|
209
|
+
Surrogate.endow self
|
210
|
+
def initialize(a) @a = a end
|
212
211
|
end
|
212
|
+
klass.new(1).should have_been_initialized_with 1
|
213
|
+
klass.new(1).instance_variable_get(:@a).should == 1
|
213
214
|
end
|
214
|
-
klass.new(1).should have_been_initialized_with 1
|
215
|
-
klass.new(1).instance_variable_get(:@a).should == 1
|
216
215
|
|
217
|
-
|
218
|
-
|
219
|
-
@a = a
|
216
|
+
specify 'even when initialize is defined before surrogate block' do
|
217
|
+
klass = Class.new do
|
218
|
+
def initialize(a) @a = a end
|
219
|
+
Surrogate.endow self
|
220
220
|
end
|
221
|
-
|
221
|
+
klass.new(1).should have_been_initialized_with 1
|
222
|
+
klass.new(1).instance_variable_get(:@a).should == 1
|
222
223
|
end
|
223
|
-
klass.new(1).should have_been_initialized_with 1
|
224
|
-
klass.new(1).instance_variable_get(:@a).should == 1
|
225
224
|
end
|
226
225
|
end
|
227
226
|
end
|
@@ -1,72 +1,151 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe 'substitute_for' do
|
4
|
+
context 'exact substitutability' do
|
5
|
+
context "returns true iff api methods and inherited methods match exactly to the other object's methods. Examples:" do
|
6
|
+
context "a surrogate with no api methods" do
|
7
|
+
let(:surrogate) { Surrogate.endow Class.new }
|
8
|
+
|
9
|
+
example "is substitutable for a class with no methods" do
|
10
|
+
surrogate.should substitute_for Class.new
|
11
|
+
end
|
12
|
+
|
13
|
+
example "is not substitutable for a class with instance methods" do
|
14
|
+
surrogate.should_not substitute_for Class.new { def foo()end }
|
15
|
+
end
|
16
|
+
|
17
|
+
example "is not substitutable for a class with class methods" do
|
18
|
+
surrogate.should_not substitute_for Class.new { def self.foo()end }
|
19
|
+
end
|
20
|
+
|
21
|
+
example "is not substitutable for a class with inherited instance methods" do
|
22
|
+
parent = Class.new { def foo()end }
|
23
|
+
surrogate.should_not substitute_for Class.new(parent)
|
24
|
+
end
|
25
|
+
|
26
|
+
example "is not substitutable for a class with inherited class methods" do
|
27
|
+
parent = Class.new { def self.foo()end }
|
28
|
+
surrogate.should_not substitute_for Class.new(parent)
|
29
|
+
end
|
30
|
+
end
|
4
31
|
|
5
|
-
context "returns true iff api methods and inherited methods match exactly to the other object's methods. Examples:" do
|
6
|
-
context "a surrogate with no api methods" do
|
7
|
-
let(:surrogate) { Surrogate.endow Class.new }
|
8
32
|
|
9
|
-
|
10
|
-
surrogate
|
11
|
-
end
|
33
|
+
context "a surrogate with an instance level api method" do
|
34
|
+
let(:surrogate) { Class.new { Surrogate.endow self; define :foo } }
|
12
35
|
|
13
|
-
|
14
|
-
|
15
|
-
|
36
|
+
example "is substitutable for a class with the same method" do
|
37
|
+
surrogate.should substitute_for Class.new { def foo()end }
|
38
|
+
end
|
16
39
|
|
17
|
-
|
18
|
-
|
19
|
-
|
40
|
+
example "is substitutable for a class that inherits the method" do
|
41
|
+
parent = Class.new { def foo()end }
|
42
|
+
surrogate.should substitute_for Class.new(parent)
|
43
|
+
end
|
20
44
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
45
|
+
example "is not substitutable for a class without the method" do
|
46
|
+
surrogate.should_not substitute_for Class.new
|
47
|
+
end
|
25
48
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
end
|
49
|
+
example "is not substitutable for a class with a different method" do
|
50
|
+
surrogate.should_not substitute_for Class.new { def bar()end }
|
51
|
+
end
|
31
52
|
|
53
|
+
example "is not substitutable for a class with additional methods" do
|
54
|
+
other = Class.new { def foo()end; def bar()end }
|
55
|
+
surrogate.should_not substitute_for other
|
56
|
+
end
|
32
57
|
|
33
|
-
|
34
|
-
|
58
|
+
example "is not substitutable for a class with the method and inerited additional methods" do
|
59
|
+
parent = Class.new { def bar()end }
|
60
|
+
surrogate.should_not substitute_for Class.new(parent) { def foo()end }
|
61
|
+
end
|
35
62
|
|
36
|
-
|
37
|
-
|
38
|
-
|
63
|
+
example "is not substitutable for a class with the method and additional class methods" do
|
64
|
+
surrogate.should_not substitute_for Class.new { def foo()end; def self.bar()end }
|
65
|
+
end
|
39
66
|
|
40
|
-
|
41
|
-
|
42
|
-
|
67
|
+
example "is not substitutable for a class with the method and inherited additional class methods" do
|
68
|
+
parent = Class.new { def self.bar()end }
|
69
|
+
surrogate.should_not substitute_for Class.new(parent) { def foo()end }
|
70
|
+
end
|
43
71
|
end
|
44
72
|
|
45
|
-
|
46
|
-
|
73
|
+
|
74
|
+
describe "it has helpful error messages" do
|
75
|
+
let(:surrogate) { Surrogate.endow Class.new }
|
76
|
+
|
77
|
+
specify 'when klass is missing an instance method' do
|
78
|
+
surrogate.define :meth
|
79
|
+
expect { surrogate.should substitute_for Class.new }.to \
|
80
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, "Was not substitutable because surrogate has extra instance methods: [:meth]")
|
81
|
+
end
|
82
|
+
|
83
|
+
specify 'when klass is missing a class method' do
|
84
|
+
surrogate = Surrogate.endow(Class.new) { define :meth }
|
85
|
+
expect { surrogate.should substitute_for Class.new }.to \
|
86
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, "Was not substitutable because surrogate has extra class methods: [:meth]")
|
87
|
+
end
|
88
|
+
|
89
|
+
specify 'when surrogate is missing an instance method' do
|
90
|
+
klass = Class.new { def meth() end }
|
91
|
+
expect { surrogate.should substitute_for klass }.to \
|
92
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, "Was not substitutable because surrogate is missing instance methods: [:meth]")
|
93
|
+
end
|
94
|
+
|
95
|
+
specify 'when surrogate is missing a class method' do
|
96
|
+
klass = Class.new { def self.meth() end }
|
97
|
+
expect { surrogate.should substitute_for klass }.to \
|
98
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, "Was not substitutable because surrogate is missing class methods: [:meth]")
|
99
|
+
end
|
100
|
+
|
101
|
+
specify 'when combined' do
|
102
|
+
surrogate = Surrogate.endow(Class.new) { define :surrogate_class_meth }.define :surrogate_instance_meth
|
103
|
+
klass = Class.new { def self.api_class_meth()end; def api_instance_meth() end }
|
104
|
+
expect { surrogate.should substitute_for klass }.to \
|
105
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, "Was not substitutable because surrogate has extra instance methods: [:surrogate_instance_meth], "\
|
106
|
+
"has extra class methods: [:surrogate_class_meth], "\
|
107
|
+
"is missing instance methods: [:api_instance_meth], "\
|
108
|
+
"is missing class methods: [:api_class_meth]")
|
109
|
+
end
|
110
|
+
|
111
|
+
specify "when negated (idk why you'd ever want this, though)" do
|
112
|
+
expect { surrogate.should_not substitute_for Class.new }.to \
|
113
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, "Should not have been substitute, but was")
|
114
|
+
end
|
47
115
|
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
|
48
120
|
|
49
|
-
|
50
|
-
|
121
|
+
context 'subset substitutability -- specified with subset: true option' do
|
122
|
+
context "returns true if api methods and inherited methods match are all implemented by other class. Examples:" do
|
123
|
+
example 'true when exact match' do
|
124
|
+
Surrogate.endow(Class.new).should substitute_for Class.new, subset: true
|
51
125
|
end
|
52
126
|
|
53
|
-
example
|
54
|
-
|
55
|
-
|
127
|
+
example 'true when other has additional instance methods and class methods' do
|
128
|
+
klass = Class.new { def self.class_meth()end; def instance_meth()end }
|
129
|
+
Surrogate.endow(Class.new).should substitute_for klass, subset: true
|
56
130
|
end
|
57
131
|
|
58
|
-
example
|
59
|
-
|
60
|
-
|
132
|
+
example 'false when other is missing instance methods' do
|
133
|
+
klass = Class.new { def self.extra_method()end; def extra_method()end }
|
134
|
+
expect { Surrogate.endow(Class.new).define(:meth).should substitute_for klass, subset:true }.to \
|
135
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, "Was not substitutable because surrogate has extra instance methods: [:meth]")
|
61
136
|
end
|
62
137
|
|
63
|
-
example
|
64
|
-
|
138
|
+
example 'false when other is missing class methods' do
|
139
|
+
klass = Class.new { def self.extra_method()end; def extra_method()end }
|
140
|
+
expect { Surrogate.endow(Class.new) { define :meth }.should substitute_for klass, subset:true }.to \
|
141
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError, "Was not substitutable because surrogate has extra class methods: [:meth]")
|
65
142
|
end
|
66
143
|
|
67
|
-
example
|
68
|
-
|
69
|
-
|
144
|
+
example 'false when other is missing instance and class methods' do
|
145
|
+
klass = Class.new { def self.extra_method()end; def extra_method()end }
|
146
|
+
expect { Surrogate.endow(Class.new) { define :class_meth }.define(:instance_meth).should substitute_for klass, subset: true }.to \
|
147
|
+
raise_error(RSpec::Expectations::ExpectationNotMetError,
|
148
|
+
"Was not substitutable because surrogate has extra instance methods: [:instance_meth], has extra class methods: [:class_meth]")
|
70
149
|
end
|
71
150
|
end
|
72
151
|
end
|
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.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
12
|
+
date: 2012-04-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70298496271040 !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: *70298496271040
|
25
25
|
description: Framework to aid in handrolling mock/spy objects.
|
26
26
|
email:
|
27
27
|
- josh.cheek@gmail.com
|