surrogate 0.3.0 → 0.3.1

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,95 +1,379 @@
1
- Explanation and examples coming soon, but here is a simple example I wrote up for a lightning talk:
1
+ About
2
+ =====
3
+
4
+ Handrolling mocks is the best, but involves more overhead than necessary, and usually has less helpful
5
+ error messages. Surrogate addresses this by endowing your objects with common things that most mocks need.
6
+ Currently it is only integrated with RSpec.
7
+
8
+
9
+ Features
10
+ ========
11
+
12
+ * Declarative syntax
13
+ * Support default values
14
+ * Easily override values
15
+ * RSpec matchers for asserting what happend (what was invoked, with what args, how many times)
16
+ * RSpec matchers for asserting the Mock's interface matches the real object
17
+ * Support for exceptions
18
+ * Queue return values
19
+ * Initialization information is always recorded
20
+
21
+
22
+ Usage
23
+ =====
24
+
25
+ **Endow** a class with surrogate abilities
2
26
 
3
27
  ```ruby
4
- require 'surrogate'
5
- require 'surrogate/rspec'
28
+ class Mock
29
+ Surrogate.endow self
30
+ end
31
+ ```
32
+
33
+ Define a **class method** by using `define` in the block when endowing your class.
34
+
35
+ ```ruby
36
+ class MockClient
37
+ Surrogate.endow self do
38
+ define(:default_url) { 'http://example.com' }
39
+ end
40
+ end
41
+
42
+ MockClient.default_url # => "http://example.com"
43
+ ```
44
+
45
+ Define an **instance method** by using `define` outside the block after endowing your class.
46
+
47
+ ```ruby
48
+ class MockClient
49
+ Surrogate.endow self
50
+ define(:request) { ['result1', 'result2'] }
51
+ end
52
+
53
+ MockClient.new.request # => ["result1", "result2"]
54
+ ```
55
+
56
+ If you care about the **arguments**, your block can receive them.
57
+
58
+ ```ruby
59
+ class MockClient
60
+ Surrogate.endow self
61
+ define(:request) { |limit| limit.times.map { |i| "result#{i.next}" } }
62
+ end
63
+
64
+ MockClient.new.request 3 # => ["result1", "result2", "result3"]
65
+ ```
66
+
67
+ You don't need a **default if you set the ivar** of the same name
68
+
69
+ ```ruby
70
+ class MockClient
71
+ Surrogate.endow self
72
+ define(:initialize) { |id| @id = id }
73
+ define :id
74
+ end
75
+ MockClient.new(12).id # => 12
76
+ ```
77
+
78
+ **Override defaults** with `will_<verb>` and `will_have_<noun>`
79
+
80
+ ```ruby
81
+ class MockMP3
82
+ Surrogate.endow self
83
+ define :play # defaults are optional, will raise error if invoked without being told what to do
84
+ define :info
85
+ end
86
+
87
+ mp3 = MockMP3.new
88
+
89
+ # verbs
90
+ mp3.will_play true
91
+ mp3.play # => true
92
+
93
+ # nouns
94
+ mp3.will_have_info artist: 'Symphony of Science', title: 'Children of Africa'
95
+ mp3.info # => {:artist=>"Symphony of Science", :title=>"Children of Africa"}
96
+ ```
97
+
98
+ **Errors** get raised
99
+
100
+ ```ruby
101
+ class MockClient
102
+ Surrogate.endow self
103
+ define :request
104
+ end
105
+
106
+ client = MockClient.new
107
+ client.will_have_request StandardError.new('Remote service unavailable')
6
108
 
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
109
+ begin
110
+ client.request
111
+ rescue StandardError => e
112
+ e # => #<StandardError: Remote service unavailable>
113
+ end
114
+ ```
115
+
116
+ **Queue** up return values
117
+
118
+ ```ruby
119
+ class MockPlayer
120
+ Surrogate.endow self
121
+ define(:move) { 20 }
122
+ end
123
+
124
+ player = MockPlayer.new
125
+ player.will_move 1, 9, 3
126
+ player.move # => 1
127
+ player.move # => 9
128
+ player.move # => 3
129
+
130
+ # then back to default behaviour (or error if none provided)
131
+ player.move # => 20
132
+ ```
133
+
134
+ You can define **initialize**
135
+
136
+ ```ruby
137
+ class MockUser
138
+ Surrogate.endow self do
139
+ define(:find) { |id| new id }
15
140
  end
141
+ define(:initialize) { |id| @id = id }
142
+ define(:id) { @id }
143
+ end
144
+
145
+ user = MockUser.find 12
146
+ user.id # => 12
147
+ ```
148
+
149
+
150
+ RSpec Integration
151
+ =================
152
+
153
+ Currently only integrated with RSpec, since that's what I use. It has some builtin matchers
154
+ for querying what happened.
155
+
156
+ Load the RSpec matchers.
157
+
158
+ ```ruby
159
+ require 'surrogate/rspec'
160
+ ```
161
+
162
+ Nouns
163
+ -----
164
+
165
+ Given this mock and assuming the following examples happen within a spec
166
+
167
+ ```ruby
168
+ class MockMP3
169
+ Surrogate.endow self
170
+ define(:info) { 'some info' }
16
171
  end
172
+ ```
173
+
174
+ Check if **was invoked** with `have_been_asked_for_its`
175
+
176
+ ```ruby
177
+ mp3.should_not have_been_asked_for_its :info
178
+ mp3.info
179
+ mp3.should have_been_asked_for_its :info
180
+ ```
181
+
182
+ Invocation **cardinality** by chaining `times(n)`
183
+
184
+ ```ruby
185
+ mp3.info
186
+ mp3.info
187
+ mp3.should have_been_asked_for_its(:info).times(2)
188
+ ```
189
+
190
+ Invocation **arguments** by chaining `with(args)`
191
+
192
+ ```ruby
193
+ mp3.info :title
194
+ mp3.should have_been_asked_for_its(:info).with(:title)
195
+ ```
196
+
197
+ Supports RSpec's `no_args` matcher (the others coming in future versions)
198
+
199
+ ```ruby
200
+ mp3.info
201
+ mp3.should have_been_asked_for_its(:info).with(no_args)
202
+ ```
203
+
204
+ Cardinality of a specific set of args `with(args)` and `times(n)`
205
+
206
+ ```ruby
207
+ mp3.info :title
208
+ mp3.info :title
209
+ mp3.info :artist
210
+ mp3.should have_been_asked_for_its(:info).with(:title).times(2)
211
+ mp3.should have_been_asked_for_its(:info).with(:artist).times(1)
212
+ ```
213
+
214
+
215
+ Verbs
216
+ -----
217
+
218
+ Given this mock and assuming the following examples happen within a spec
219
+
220
+ ```ruby
221
+ class MockMP3
222
+ Surrogate.endow self
223
+ define(:play) { true }
224
+ end
225
+ ```
226
+
227
+ Check if **was invoked** with `have_been_told_to`
228
+
229
+ ```ruby
230
+ mp3.should_not have_been_told_to :play
231
+ mp3.play
232
+ mp3.should have_been_told_to :play
233
+ ```
234
+
235
+ Also supports the same `with(args)` and `times(n)` that nouns have.
236
+
237
+
238
+ Initialization
239
+ --------------
240
+
241
+ Query with `have_been_initialized_with`, which is exactly the same as saying `have_been_told_to(:initialize).with(...)`
242
+
243
+ ```ruby
244
+ class MockUser
245
+ Surrogate.endow self
246
+ define(:initialize) { |id| @id = id }
247
+ define :id
248
+ end
249
+ user = MockUser.new 12
250
+ user.id.should == 12
251
+ user.should have_been_initialized_with 12
252
+ ```
253
+
254
+ Initialization is **always recorded**, so that you don't have to override it just to be able to query.
255
+
256
+ ```ruby
257
+ class MockUser < Struct.new(:id)
258
+ Surrogate.endow self
259
+ end
260
+ user = MockUser.new 12
261
+ user.id.should == 12
262
+ user.should have_been_initialized_with 12
263
+ ```
264
+
265
+
266
+ Substitutability
267
+ ----------------
17
268
 
269
+ After you've implemented the real version of your mock (assuming a [top-down](http://vimeo.com/31267109) style of development),
270
+ how do you prevent your real object from getting out of synch with your mock?
271
+
272
+ Assert that your mock has the **same interface** as your real class.
273
+ This will fail if the mock inherits methods methods not on the real class. And it will fail
274
+ if the real class has or lacks any methods defined on the mock or inherited by the mock.
275
+
276
+ Presently, it will ignore methods defined directly in the mock (as it adds quite a few of its own methods,
277
+ and generally considers them to be helpers). In a future version, you will be able to tell it to treat other methods
278
+ as part of the API (will fail if they don't match, and maybe record their values).
279
+
280
+ ```ruby
18
281
  class User
282
+ def initialize(id)end
283
+ def id()end
284
+ end
285
+
286
+ class MockUser
287
+ Surrogate.endow self
288
+ define(:initialize) { |id| @id = id }
289
+ define :id
290
+ end
291
+
292
+ # they are the same
293
+ MockUser.should substitute_for User
294
+
295
+ # mock has extra method
296
+ MockUser.define :name
297
+ MockUser.should_not substitute_for User
298
+
299
+ # the same again via inheritance
300
+ class UserWithName < User
19
301
  def name()end
20
- def phone_numbers()end
21
- def add_phone_number()end
22
302
  end
303
+ MockUser.should substitute_for UserWithName
23
304
 
24
- describe do
25
- it 'ensures the mock lib looks like real lib' do
26
- Mock::User.should substitute_for User
27
- end
305
+ # real class has extra methods
306
+ class UserWithNameAndAddress < UserWithName
307
+ def address()end
308
+ end
309
+ MockUser.should_not substitute_for UserWithNameAndAddress
310
+ ```
28
311
 
29
- let(:user) { Mock::User.new }
312
+ Sometimes you don't want to have to implement the entire interface.
313
+ In these cases, you can assert that the methods on the mock are a **subset**
314
+ of the methods on the real class.
30
315
 
31
- example 'you can tell it how to behave and ask what happened with it' do
32
- user.will_have_name "Sally"
316
+ ```ruby
317
+ class User
318
+ def initialize(id)end
319
+ def id()end
320
+ def name()end
321
+ end
33
322
 
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
323
+ class MockUser
324
+ Surrogate.endow self
325
+ define(:initialize) { |id| @id = id }
326
+ define :id
38
327
  end
328
+
329
+ # doesn't matter that real user has a name as long as it has initialize and id
330
+ MockUser.should substitute_for User, subset: true
331
+
332
+ # but now it fails b/c it has no addres
333
+ MockUser.define :address
334
+ MockUser.should_not substitute_for User, subset: true
39
335
  ```
40
336
 
41
337
 
42
- TODO
43
- ----
338
+ How do I introduce my mocks?
339
+ ============================
44
340
 
45
- * substitutability
46
- * add methods for substitutability
341
+ This is known as dependency injection. There are many ways you can do this, you can pass the object into
342
+ the initializer, you can pass a factory to your class, you can give the class that depends on the mock a
343
+ setter and then override it whenever you feel it is necessary, you can use RSpec's `#stub` method to put
344
+ it into place.
47
345
 
346
+ Personally, I use [Deject](https://rubygems.org/gems/deject) another gem I wrote. For more on why I feel
347
+ it is a better solution than the above methods, see it's [readme](https://github.com/JoshCheek/deject/tree/938edc985c65358c074a7c7b7bbf18dc11e9450e#why-write-this).
48
348
 
49
- Features for future vuersions
50
- -----------------------------
51
349
 
52
- * change queue notation from will_x_qeue(1,2,3) to will_x(1,2,3)
53
- * arity option
54
- * support for raising errors
55
- * need some way to talk about and record blocks being passed
56
- * support all rspec matchers (RSpec::Mocks::ArgumentMatchers)
57
- * assertions for order of invocations & methods
350
+ But why write this?
351
+ ===================
58
352
 
353
+ Need to put an explanation here soon. In the meantime, I wrote a [blog](http://blog.8thlight.com/josh-cheek/2011/11/28/three-reasons-to-roll-your-own-mocks.html) that touches on the reasons.
59
354
 
60
355
 
61
- Future subset substitutability
356
+ Special Thanks
357
+ ==============
62
358
 
63
- # ===== Substitutability =====
359
+ * [Corey Haines](http://coreyhaines.com/) for pairing on it with me
360
+ * [8th Light](http://8thlight.com/) for giving me time to work on this during our weekly Wazas, and the general encouragement and interest
64
361
 
65
- # real user is not a suitable substitute if missing methods that mock user has
66
- user_class.should_not substitute_for Class.new
67
362
 
68
- # real user must have all of mock user's methods to be substitutable
69
- substitutable_real_user_class = Class.new do
70
- def self.find() end
71
- def initialize(id) end
72
- def id() end
73
- def name() end
74
- def address() end
75
- def phone_numbers() end
76
- def add_phone_number(area_code, number) end
77
- end
78
- user_class.should substitute_for substitutable_real_user_class
79
- user_class.should be_subset_of substitutable_real_user_class
363
+ TODO
364
+ ----
80
365
 
81
- # real user class is not a suitable substitutable if has extra methods, but is suitable subset
82
- real_user_class = substitutable_real_user_class.clone
83
- def real_user_class.some_class_meth() end
84
- user_class.should_not substitute_for real_user_class
85
- user_class.should be_subset_of real_user_class
366
+ * Add a better explanation for motivations
367
+ * Figure out whether I'm supposed to be using clone or dup for the object -.^ (looks like there may also be an `initialize_copy` method I can take advantage of instead of crazy stupid shit I'm doing now)
86
368
 
87
- real_user_class = substitutable_real_user_class.clone
88
- real_user_class.send(:define_method, :some_instance_method) {}
89
- user_class.should_not substitute_for real_user_class
90
- user_class.should be_subset_of real_user_class
91
369
 
92
- # subset substitutability does not work for superset
93
- real_user_class = substitutable_real_user_class.clone
94
- real_user_class.undef_method :address
95
- user_class.should_not be_subset_of real_user_class
370
+ Future Features
371
+ ---------------
372
+
373
+ * Support all RSpec matchers (hash_including, anything, etc. see them in RSpec::Mocks::ArgumentMatchers)
374
+ * have some sort of reinitialization that can hook into setup/teardown steps of test suite
375
+ * Support arity checking as part of substitutability
376
+ * Support for blocks
377
+ * Ability to disassociate the method name from the test (e.g. you shouldn't need to change a test just because you change a name)
378
+ * declare normal methods as being part of the API (e.g. for inheritance)
379
+ * assertions for order of invocations & methods
@@ -2,16 +2,16 @@ class Surrogate
2
2
 
3
3
  # Adds surrogate behaviour to your class / singleton class / instances
4
4
  #
5
- # please refactor me!
5
+ # please refactor me! ...may not be possible :(
6
6
  class Endower
7
- def self.endow(klass, &playlist)
8
- new(klass, &playlist).endow
7
+ def self.endow(klass, &block)
8
+ new(klass, &block).endow
9
9
  end
10
10
 
11
- attr_accessor :klass, :playlist
11
+ attr_accessor :klass, :block
12
12
 
13
- def initialize(klass, &playlist)
14
- self.klass, self.playlist = klass, playlist
13
+ def initialize(klass, &block)
14
+ self.klass, self.block = klass, block
15
15
  end
16
16
 
17
17
  def endow
@@ -33,7 +33,7 @@ class Surrogate
33
33
  def endow_singleton_class
34
34
  hatchery = add_hatchery_to singleton
35
35
  enable_defining_methods singleton
36
- singleton.module_eval &playlist if playlist
36
+ singleton.module_eval &block if block
37
37
  klass.instance_variable_set :@hatchling, Hatchling.new(klass, hatchery)
38
38
  klass
39
39
  end
@@ -49,11 +49,7 @@ class Surrogate
49
49
 
50
50
  def add_helpers_for(method_name, helper_name)
51
51
  klass.send :define_method, helper_name do |*args, &block|
52
- if args.size == 1
53
- @hatchling.prepare_method method_name, args, &block
54
- else
55
- @hatchling.prepare_method_queue method_name, args, &block
56
- end
52
+ @hatchling.prepare_method method_name, args, &block
57
53
  self
58
54
  end
59
55
  end
@@ -1,6 +1,7 @@
1
1
  class Surrogate
2
2
  UnknownMethod = Class.new StandardError
3
3
 
4
+
4
5
  # This contains the unique behaviour for each instance
5
6
  # It handles method invocation and records the appropriate information
6
7
  class Hatchling
@@ -17,31 +18,34 @@ class Surrogate
17
18
  def invoke_method(method_name, args, &block)
18
19
  invoked_methods[method_name] << args
19
20
  return get_default method_name, args unless has_ivar? method_name
20
- ivar = get_ivar method_name
21
-
22
- # This may soon need classes for each type which know how to invoke themselves
23
- case ivar
24
- when MethodQueue
25
- play_from_queue ivar, method_name
26
- when Exception
27
- raise ivar
28
- else
29
- ivar
30
- end
21
+ Value.factory(get_ivar method_name).value(self, method_name)
31
22
  end
32
23
 
33
24
  def prepare_method(method_name, args, &block)
34
- set_ivar method_name, *args
35
- end
36
-
37
- def prepare_method_queue(method_name, args, &block)
38
- set_ivar method_name, MethodQueue.new(args)
25
+ set_ivar method_name, Value.factory(*args, &block)
39
26
  end
40
27
 
41
28
  def invocations(method_name)
42
29
  invoked_methods[method_name]
43
30
  end
44
31
 
32
+ # maybe these four should be extracted into their own class
33
+ def has_ivar?(method_name)
34
+ instance.instance_variable_defined? "@#{method_name}"
35
+ end
36
+
37
+ def set_ivar(method_name, value)
38
+ instance.instance_variable_set "@#{method_name}", value
39
+ end
40
+
41
+ def get_ivar(method_name)
42
+ instance.instance_variable_get "@#{method_name}"
43
+ end
44
+
45
+ def unset_ivar(method_name)
46
+ instance.send :remove_instance_variable, "@#{method_name}"
47
+ end
48
+
45
49
  private
46
50
 
47
51
  def invoked_methods
@@ -57,33 +61,11 @@ class Surrogate
57
61
  end
58
62
  end
59
63
 
60
- def play_from_queue(queue, method_name)
61
- result = queue.dequeue
62
- unset_ivar method_name if queue.empty?
63
- result
64
- end
65
-
66
64
  def must_know(method_name)
67
65
  return if api_methods.has_key? method_name
68
66
  known_methods = api_methods.keys.map(&:to_s).map(&:inspect).join ', '
69
67
  raise UnknownMethod, "doesn't know \"#{method_name}\", only knows #{known_methods}"
70
68
  end
71
-
72
- def has_ivar?(method_name)
73
- instance.instance_variable_defined? "@#{method_name}"
74
- end
75
-
76
- def set_ivar(method_name, value)
77
- instance.instance_variable_set "@#{method_name}", value
78
- end
79
-
80
- def get_ivar(method_name)
81
- instance.instance_variable_get "@#{method_name}"
82
- end
83
-
84
- def unset_ivar(method_name)
85
- instance.send :remove_instance_variable, "@#{method_name}"
86
- end
87
69
  end
88
70
  end
89
71
 
@@ -1,2 +1,4 @@
1
+ # Maybe I should be my own gem?
2
+ require 'surrogate'
1
3
  require 'surrogate/rspec/api_method_matchers'
2
4
  require 'surrogate/rspec/substitutability_matchers'
@@ -0,0 +1,78 @@
1
+ class Surrogate
2
+
3
+ # Superclass for all types of values. Where a value is anything stored
4
+ # in an instance variable on a surrogate, intended to be returned by an api method
5
+ class Value
6
+
7
+ # convert raw arguments into a value
8
+ def self.factory(*args, &block)
9
+ arg = args.first
10
+ if args.size > 1
11
+ MethodQueue.new args
12
+ elsif arg.kind_of? Exception
13
+ Raisable.new arg
14
+ elsif arg.kind_of? Value
15
+ Recursive.new arg
16
+ else
17
+ Value.new arg
18
+ end
19
+ end
20
+
21
+ def initialize(value)
22
+ @value = value
23
+ end
24
+
25
+ def value(hatchling, method_name)
26
+ @value
27
+ end
28
+
29
+ def factory(*args, &block)
30
+ self.class.factory(*args, &block)
31
+ end
32
+ end
33
+ end
34
+
35
+
36
+ # the current set of possible values
37
+
38
+ class Surrogate
39
+ class Value
40
+
41
+ class Raisable < Value
42
+ def value(*)
43
+ raise @value
44
+ end
45
+ end
46
+
47
+
48
+ class Recursive < Value
49
+ def value(hatchling, method_name)
50
+ @value.value hatchling, method_name
51
+ end
52
+ end
53
+
54
+
55
+ class MethodQueue < Value
56
+ QueueEmpty = Class.new StandardError
57
+
58
+ def value(hatchling, method_name)
59
+ factory(dequeue).value(hatchling, method_name)
60
+ ensure
61
+ hatchling.unset_ivar method_name if empty?
62
+ end
63
+
64
+ def queue
65
+ @value
66
+ end
67
+
68
+ def dequeue
69
+ raise QueueEmpty if empty?
70
+ queue.shift
71
+ end
72
+
73
+ def empty?
74
+ queue.empty?
75
+ end
76
+ end
77
+ end
78
+ end
@@ -1,3 +1,3 @@
1
1
  class Surrogate
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
data/lib/surrogate.rb CHANGED
@@ -2,16 +2,15 @@ require 'surrogate/version'
2
2
  require 'surrogate/hatchling'
3
3
  require 'surrogate/hatchery'
4
4
  require 'surrogate/options'
5
- require 'surrogate/method_queue'
5
+ require 'surrogate/values'
6
6
  require 'surrogate/endower'
7
7
  require 'surrogate/api_comparer'
8
8
 
9
9
  class Surrogate
10
10
  UnpreparedMethodError = Class.new StandardError
11
11
 
12
- # TODO: Find a new name that isn't "playlist"
13
- def self.endow(klass, &playlist)
14
- Endower.endow klass, &playlist
12
+ def self.endow(klass, &block)
13
+ Endower.endow klass, &block
15
14
  klass
16
15
  end
17
16
  end
@@ -125,14 +125,21 @@ describe Surrogate do
125
125
  def add_phone_number(area_code, number) end
126
126
  end
127
127
  user_class.should substitute_for substitutable_real_user_class
128
+ user_class.should substitute_for substitutable_real_user_class, subset: true
128
129
 
129
- # real user class is not a suitable substitutable if has extra methods
130
+ # when real user class has extra methods, it is only substitutable as a subset
130
131
  real_user_class = substitutable_real_user_class.clone
131
132
  def real_user_class.some_class_meth() end
132
133
  user_class.should_not substitute_for real_user_class
133
134
 
134
- real_user_class = substitutable_real_user_class.clone
135
+ real_user_class = substitutable_real_user_class.dup
135
136
  real_user_class.send(:define_method, :some_instance_method) {}
136
137
  user_class.should_not substitute_for real_user_class
138
+ user_class.should substitute_for real_user_class, subset: true
139
+
140
+ # subset substitutability does not work for superset
141
+ real_user_class = substitutable_real_user_class.dup
142
+ real_user_class.send :undef_method, :address
143
+ user_class.should_not substitute_for real_user_class, subset: true
137
144
  end
138
145
  end
data/spec/spec_helper.rb CHANGED
@@ -1,2 +1 @@
1
- require 'surrogate'
2
1
  require 'surrogate/rspec'
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.3.0
4
+ version: 0.3.1
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-30 00:00:00.000000000 Z
12
+ date: 2012-05-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70298496271040 !ruby/object:Gem::Requirement
16
+ requirement: &70186184231320 !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: *70298496271040
24
+ version_requirements: *70186184231320
25
25
  description: Framework to aid in handrolling mock/spy objects.
26
26
  email:
27
27
  - josh.cheek@gmail.com
@@ -39,11 +39,11 @@ files:
39
39
  - lib/surrogate/endower.rb
40
40
  - lib/surrogate/hatchery.rb
41
41
  - lib/surrogate/hatchling.rb
42
- - lib/surrogate/method_queue.rb
43
42
  - lib/surrogate/options.rb
44
43
  - lib/surrogate/rspec.rb
45
44
  - lib/surrogate/rspec/api_method_matchers.rb
46
45
  - lib/surrogate/rspec/substitutability_matchers.rb
46
+ - lib/surrogate/values.rb
47
47
  - lib/surrogate/version.rb
48
48
  - spec/acceptance_spec.rb
49
49
  - spec/defining_api_methods_spec.rb
@@ -1,16 +0,0 @@
1
- class Surrogate
2
- class MethodQueue < Struct.new(:queue)
3
- QueueEmpty = Class.new StandardError
4
-
5
- def dequeue
6
- raise QueueEmpty if empty?
7
- current = queue.shift
8
- raise current if current.kind_of? Exception
9
- current
10
- end
11
-
12
- def empty?
13
- queue.empty?
14
- end
15
- end
16
- end