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 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
  ----
@@ -1,6 +1,6 @@
1
1
  class Surrogate
2
2
 
3
- # adds surrogate behaviour to your class / singleton class / instances
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
- a_hatchery_for klass
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 = a_hatchery_for singleton
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 :@surrogate, Hatchling.new(klass, hatchery)
37
+ klass.instance_variable_set :@hatchling, Hatchling.new(klass, hatchery)
39
38
  klass
40
39
  end
41
40
 
42
- # yeesh :( try to find a better way to do this
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 unless meth == :initialize && !@hijacking_initialize
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
- @surrogate.invocations method_name
68
+ @hatchling.invocations method_name
86
69
  end
87
70
  end
88
71
 
89
- def a_hatchery_for(klass)
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
@@ -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
- defines_methods
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
- add_api_methods_for method_name
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
- # here we need to find better domain terminology
28
- def add_api_methods_for(method_name)
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
- @surrogate.invoke_method method_name, args, &block
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
- # verbs
34
- klass.send :define_method, "will_#{method_name}" do |*args, &block|
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
- @surrogate.prepare_method method_name, args, &block
53
+ @hatchling.prepare_method method_name, args, &block
37
54
  else
38
- @surrogate.prepare_method_queue method_name, args, &block
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
@@ -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
@@ -228,10 +228,6 @@ class Surrogate
228
228
  use_case.match?
229
229
  end
230
230
 
231
- chain :nothing do
232
- use_case.expected_arguments = nothing
233
- end
234
-
235
231
  failure_message_for_should do
236
232
  use_case.failure_message_for_should
237
233
  end
@@ -1,24 +1,34 @@
1
1
  class Surrogate
2
- module RSpec
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
- comparison = nil
4
+ comparison = nil
5
+ subset_only = options[:subset]
7
6
 
8
- match do |mocked_class|
9
- comparison = ApiComparer.new(mocked_class, original_class).compare
10
- (comparison[:instance].values + comparison[:class].values).inject(:+).empty?
11
- end
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
- failure_message_for_should do
14
- "Should have been substitute, but found these differences #{comparison.inspect}"
15
- end
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
- failure_message_for_should_not do
18
- "Should not have been substitute, but was"
19
- end
20
- end
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
-
@@ -1,3 +1,3 @@
1
1
  class Surrogate
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -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
- mocked_subclass = Surrogate.endow Class.new subclass
198
- mocked_subclass.define :abc
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(1) }.to raise_error ArgumentError, 'wrong number of arguments(1 for 0)'
203
+ expect { mocked_class.new 1 }.to raise_error ArgumentError, 'wrong number of arguments(1 for 0)'
205
204
  end
206
205
 
207
- specify 'recorded regardless of when initialize is defined in relation to mock' do
208
- klass = Class.new do
209
- Surrogate.endow self
210
- def initialize(a)
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
- klass = Class.new do
218
- def initialize(a)
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
- Surrogate.endow self
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
- example "is substitutable for a class with no methods" do
10
- surrogate.should substitute_for Class.new
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
- example "is not substitutable for a class with instance methods" do
14
- surrogate.should_not substitute_for Class.new { def foo()end }
15
- end
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
- 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
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
- 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
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
- 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
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
- context "a surrogate with an instance level api method" do
34
- let(:surrogate) { Class.new { Surrogate.endow self; define :foo } }
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
- example "is substitutable for a class with the same method" do
37
- surrogate.should substitute_for Class.new { def foo()end }
38
- end
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
- 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)
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
- example "is not substitutable for a class without the method" do
46
- surrogate.should_not substitute_for Class.new
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
- example "is not substitutable for a class with a different method" do
50
- surrogate.should_not substitute_for Class.new { def bar()end }
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 "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
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 "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 }
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 "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 }
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 "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 }
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.2.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-20 00:00:00.000000000 Z
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: &70270582700600 !ruby/object:Gem::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: *70270582700600
24
+ version_requirements: *70298496271040
25
25
  description: Framework to aid in handrolling mock/spy objects.
26
26
  email:
27
27
  - josh.cheek@gmail.com