spy 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 25f96e1254110c34d4b25ace27db39cf4933cc2a
4
+ data.tar.gz: 84320005a4c47158b70dc86fca661f6ae95f6ad6
5
+ SHA512:
6
+ metadata.gz: 340277d830dfb87085d61fb443b834cb6636e8dda7b5d2af0166aab6835918747343849efed3b56032071d5d44b49cebaca0edb04df0c7997c10006cdb6cc897
7
+ data.tar.gz: 2b147cc08e3612270d8f18789bc4116621334e6da864bb3299b79ce857247513c467e4bf7f27e8c0354b064801445b392856489758fd6456015d44000dad987d
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - "1.9.3"
4
+ - "2.0.0"
4
5
  - jruby-19mode
5
- - rbx-19mode
data/Gemfile CHANGED
@@ -5,5 +5,5 @@ gemspec
5
5
  gem 'pry'
6
6
  gem 'pry-nav'
7
7
  gem 'yard'
8
- gem 'redcarpet'
8
+ gem 'redcarpet', platforms: :mri
9
9
  gem 'rake'
@@ -19,9 +19,7 @@ module Spy
19
19
  raise "#{base_module.inspect} is not a kind of Module" unless base_module.is_a? Module
20
20
  raise "#{constant_name.inspect} is not a kind of Symbol" unless constant_name.is_a? Symbol
21
21
  @base_module, @constant_name = base_module, constant_name.to_sym
22
- @original_value = nil
23
- @new_value = nil
24
- @previously_defined = nil
22
+ @original_value = @new_value = @previously_defined = nil
25
23
  end
26
24
 
27
25
  # full name of spied constant
@@ -33,11 +31,12 @@ module Spy
33
31
  # @param opts [Hash{force => false}] set :force => true if you want it to ignore if the constant exists
34
32
  # @return [self]
35
33
  def hook(opts = {})
34
+ opts[:force] ||= false
36
35
  Nest.fetch(base_module).add(self)
37
36
  Agency.instance.recruit(self)
38
- opts[:force] ||= false
37
+
39
38
  @previously_defined = currently_defined?
40
- if @previously_defined || !opts[:force]
39
+ if previously_defined? || !opts[:force]
41
40
  @original_value = base_module.const_get(constant_name, false)
42
41
  end
43
42
  and_return(@new_value)
@@ -50,10 +49,9 @@ module Spy
50
49
  Nest.get(base_module).remove(self)
51
50
  Agency.instance.retire(self)
52
51
 
53
- if @previously_defined
54
- and_return(@original_value)
55
- end
56
- @original_value = nil
52
+ and_return(@original_value) if previously_defined?
53
+
54
+ @original_value = @previously_defined = nil
57
55
  self
58
56
  end
59
57
 
@@ -35,6 +35,8 @@ module Spy
35
35
  def remove(spy)
36
36
  if @hooked_constants[spy.constant_name] == spy
37
37
  @hooked_constants.delete(spy.constant_name)
38
+ else
39
+ raise "#{spy.constant_name} was never added"
38
40
  end
39
41
  self
40
42
  end
@@ -38,10 +38,11 @@ module Spy
38
38
  raise "#{base_object} method '#{method_name}' has already been hooked" if hooked?
39
39
 
40
40
  hook_opts[:force] ||= base_object.is_a?(Double)
41
- if (base_object_respond_to?(method_name, true)) || !hook_opts[:force]
41
+ hook_opts[:visibility] ||= original_method_visibility
42
+
43
+ if original_method_visibility || !hook_opts[:force]
42
44
  @original_method = current_method
43
45
  end
44
- hook_opts[:visibility] ||= method_visibility
45
46
 
46
47
  base_object.send(define_method_with, method_name, override_method)
47
48
 
@@ -61,7 +62,7 @@ module Spy
61
62
 
62
63
  if original_method && method_owner == original_method.owner
63
64
  original_method.owner.send(:define_method, method_name, original_method)
64
- original_method.owner.send(method_visibility, method_name) if method_visibility
65
+ original_method.owner.send(original_method_visibility, method_name) if original_method_visibility
65
66
  else
66
67
  method_owner.send(:remove_method, method_name)
67
68
  end
@@ -83,18 +84,10 @@ module Spy
83
84
  #
84
85
  # @return [self]
85
86
  def and_return(value = nil)
87
+ raise ArgumentError.new("value and block conflict. Choose one") if !(value.nil? || value.is_a?(Hash) && value.has_key?(:force)) && block_given?
86
88
  if block_given?
87
89
  @plan = Proc.new
88
- if value.nil? || value.is_a?(Hash) && value.has_key?(:force)
89
- if !(value.is_a?(Hash) && value[:force]) &&
90
- original_method &&
91
- original_method.arity >=0 &&
92
- @plan.arity > original_method.arity
93
- raise ArgumentError.new "The original method only has an arity of #{original_method.arity} you have an arity of #{@plan.arity}"
94
- end
95
- else
96
- raise ArgumentError.new("value and block conflict. Choose one") if !value.nil?
97
- end
90
+ check_for_too_many_arguments!(@plan)
98
91
  else
99
92
  @plan = Proc.new { value }
100
93
  end
@@ -114,11 +107,10 @@ module Spy
114
107
  # tells the spy to call the original method
115
108
  # @return [self]
116
109
  def and_call_through
117
- raise "can only call through if original method is set" unless method_visibility
118
- if original_method
119
- @plan = original_method
120
- else
121
- @plan = Proc.new do |*args, &block|
110
+ @plan = Proc.new do |*args, &block|
111
+ if original_method
112
+ original_method.call(*args, &block)
113
+ else
122
114
  base_object.send(:method_missing, method_name, *args, &block)
123
115
  end
124
116
  end
@@ -182,9 +174,12 @@ module Spy
182
174
  # method.
183
175
  def invoke(object, args, block, called_from)
184
176
  check_arity!(args.size)
185
- result = @plan ? @plan.call(*args, &block) : nil
177
+ result = if @plan
178
+ check_for_too_many_arguments!(@plan)
179
+ @plan.call(*args, &block)
180
+ end
186
181
  ensure
187
- calls << CallLog.new(object,called_from, args, block, result)
182
+ calls << CallLog.new(object, called_from, args, block, result)
188
183
  end
189
184
 
190
185
  # reset the call log
@@ -206,43 +201,32 @@ module Spy
206
201
  METHOD
207
202
  end
208
203
 
209
- def call_with_yield(&block)
210
- raise "no block sent" unless block
211
- value = nil
212
- @args_to_yield.each do |args|
213
- if block.arity > -1 && args.length != block.arity
214
- @error_generator.raise_wrong_arity_error args, block.arity
215
- end
216
- value = @eval_context ? @eval_context.instance_exec(*args, &block) : block.call(*args)
217
- end
218
- value
219
- end
220
-
221
204
  def clear_method!
222
205
  @hooked = false
223
- @hook_opts = @original_method = @arity_range = @method_visibility = @method_owner= nil
206
+ @hook_opts = @original_method = @arity_range = @original_method_visibility = @method_owner= nil
224
207
  end
225
208
 
226
- def method_visibility
227
- @method_visibility ||=
228
- if base_object_respond_to?(method_name)
229
- if original_method && original_method.owner.protected_method_defined?(method_name)
230
- :protected
231
- else
232
- :public
233
- end
234
- elsif base_object_respond_to?(method_name, true)
235
- :private
236
- end
209
+ def original_method_visibility
210
+ @original_method_visibility ||= method_visibility_of(method_name)
237
211
  end
238
212
 
239
- def base_object_respond_to?(method_name, include_private = false)
213
+ def method_visibility_of(method_name, all = true)
240
214
  if @singleton_method
241
- base_object.respond_to?(method_name, include_private)
215
+ if base_object.public_methods(all).include?(method_name)
216
+ :public
217
+ elsif base_object.protected_methods(all).include?(method_name)
218
+ :protected
219
+ elsif base_object.private_methods(all).include?(method_name)
220
+ :private
221
+ end
242
222
  else
243
- base_object.instance_methods.include?(method_name) || (
244
- include_private && base_object.private_instance_methods.include?(method_name)
245
- )
223
+ if base_object.public_instance_methods(all).include?(method_name)
224
+ :public
225
+ elsif base_object.protected_instance_methods(all).include?(method_name)
226
+ :protected
227
+ elsif base_object.private_instance_methods(all).include?(method_name)
228
+ :private
229
+ end
246
230
  end
247
231
  end
248
232
 
@@ -251,11 +235,41 @@ module Spy
251
235
  end
252
236
 
253
237
  def check_arity!(arity)
254
- self.class.check_arity_against_range!(arity_range, arity)
238
+ return unless arity_range
239
+ if arity < arity_range.min
240
+ raise ArgumentError.new("wrong number of arguments (#{arity} for #{arity_range.min})")
241
+ elsif arity > arity_range.max
242
+ raise ArgumentError.new("wrong number of arguments (#{arity} for #{arity_range.max})")
243
+ end
244
+ end
245
+
246
+ def check_for_too_many_arguments!(block)
247
+ return unless arity_range
248
+ min_arity = block.arity
249
+ min_arity = min_arity.abs - 1 if min_arity < 0
250
+
251
+ if min_arity > arity_range.max
252
+ raise ArgumentError.new("block requires #{min_arity} arguments while original_method require a maximum of #{arity_range.max}")
253
+ end
255
254
  end
256
255
 
257
256
  def arity_range
258
- @arity_range ||= self.class.arity_range_of(original_method) if original_method
257
+ @arity_range ||=
258
+ if original_method
259
+ min = max = 0
260
+ original_method.parameters.each do |type,_|
261
+ case type
262
+ when :req
263
+ min += 1
264
+ max += 1
265
+ when :opt
266
+ max += 1
267
+ when :rest
268
+ max = Float::INFINITY
269
+ end
270
+ end
271
+ (min..max)
272
+ end
259
273
  end
260
274
 
261
275
  def current_method
@@ -267,34 +281,6 @@ module Spy
267
281
  end
268
282
 
269
283
  class << self
270
- # @private
271
- def arity_range_of(block)
272
- raise "#{block.inspect} does not respond to :parameters" unless block.respond_to?(:parameters)
273
- min = max = 0
274
- block.parameters.each do |type,_|
275
- case type
276
- when :req
277
- min += 1
278
- max += 1
279
- when :opt
280
- max += 1
281
- when :rest
282
- max = Float::INFINITY
283
- end
284
- end
285
- (min..max)
286
- end
287
-
288
- # @private
289
- def check_arity_against_range!(arity_range, arity)
290
- return unless arity_range
291
- if arity < arity_range.min
292
- raise ArgumentError.new("wrong number of arguments (#{arity} for #{arity_range.min})")
293
- elsif arity > arity_range.max
294
- raise ArgumentError.new("wrong number of arguments (#{arity} for #{arity_range.max})")
295
- end
296
- end
297
-
298
284
  # retrieve the method spy from an object
299
285
  # @param base_object
300
286
  # @param method_name [Symbol]
@@ -316,12 +302,18 @@ module Spy
316
302
 
317
303
  # retrieve all the spies from a given object
318
304
  # @param base_object
305
+ # @param singleton_method [Boolean] (true) only get singleton_method_spies
319
306
  # @return [Array<Subroutine>]
320
- def get_spies(base_object)
307
+ def get_spies(base_object, singleton_methods = true)
308
+ if singleton_methods
321
309
  all_methods = base_object.public_methods(false) +
322
310
  base_object.protected_methods(false) +
323
311
  base_object.private_methods(false)
324
- all_methods += base_object.instance_methods(false) + base_object.private_instance_methods(false) if base_object.respond_to?(:instance_methods)
312
+ else
313
+ all_methods = base_object.instance_methods(false) +
314
+ base_object.private_instance_methods(false)
315
+ end
316
+
325
317
  all_methods.map do |method_name|
326
318
  Agency.instance.find(get_spy_id(base_object.method(method_name)))
327
319
  end.compact
@@ -1,3 +1,3 @@
1
1
  module Spy
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
@@ -74,8 +74,7 @@ module Spy
74
74
  end
75
75
 
76
76
  def test_spy_can_hook_a_non_existent_method_if_param_set
77
- spy = Subroutine.new(@pen, :no_method).and_return(:yep)
78
- spy.hook(force: true)
77
+ Subroutine.new(@pen, :no_method).hook(force:true).and_return(:yep)
79
78
  assert_equal :yep, @pen.no_method
80
79
  end
81
80
 
@@ -188,24 +187,39 @@ module Spy
188
187
  def test_hook_mimics_public_visibility
189
188
  spy_on(@pen, :public_method)
190
189
  assert @pen.singleton_class.public_method_defined? :public_method
191
- refute @pen.singleton_class.protected_method_defined? :public_method
192
- refute @pen.singleton_class.private_method_defined? :public_method
193
190
  end
194
191
 
195
192
  def test_hook_mimics_protected_visibility
196
193
  spy_on(@pen, :protected_method)
197
- refute @pen.singleton_class.public_method_defined? :protected_method
198
194
  assert @pen.singleton_class.protected_method_defined? :protected_method
199
- refute @pen.singleton_class.private_method_defined? :protected_method
200
195
  end
201
196
 
202
197
  def test_hook_mimics_private_visibility
203
198
  spy_on(@pen, :private_method)
204
- refute @pen.singleton_class.public_method_defined? :private_method
205
- refute @pen.singleton_class.protected_method_defined? :private_method
206
199
  assert @pen.singleton_class.private_method_defined? :private_method
207
200
  end
208
201
 
202
+ def test_hook_mimics_class_public_visibility
203
+ spy_on(Pen, :public_method)
204
+ assert Pen.public_method_defined? :public_method
205
+ Spy.off(Pen, :public_method)
206
+ assert Pen.public_method_defined? :public_method
207
+ end
208
+
209
+ def test_hook_mimics_class_protected_visibility
210
+ spy_on(Pen, :protected_method)
211
+ assert Pen.protected_method_defined? :protected_method
212
+ Spy.off(Pen, :protected_method)
213
+ assert Pen.protected_method_defined? :protected_method
214
+ end
215
+
216
+ def test_hook_mimics_class_private_visibility
217
+ spy_on(Pen, :private_method)
218
+ assert Pen.private_method_defined? :private_method
219
+ Spy.off(Pen, :private_method)
220
+ assert Pen.private_method_defined? :private_method
221
+ end
222
+
209
223
  def test_spy_get_can_retrieve_a_spy
210
224
  pen_write_spy = spy_on(@pen, :write).and_return(:hello)
211
225
  assert_equal :hello, @pen.write(:world)
@@ -50,6 +50,18 @@ class Pen
50
50
  def another
51
51
  "another"
52
52
  end
53
+
54
+ def public_method
55
+ end
56
+
57
+ protected
58
+ def protected_method
59
+ end
60
+
61
+ private
62
+ def private_method
63
+ end
64
+
53
65
  end
54
66
  end
55
67
 
metadata CHANGED
@@ -1,62 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
5
- prerelease:
4
+ version: 0.2.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Ryan Ong
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-02-25 00:00:00.000000000 Z
11
+ date: 2013-02-26 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: minitest
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: 4.5.0
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: 4.5.0
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rspec-core
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rspec-expectations
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  description: A simple mocking library that doesn't spies your intelligence.
@@ -109,27 +102,26 @@ files:
109
102
  - test/test_helper.rb
110
103
  homepage: ''
111
104
  licenses: []
105
+ metadata: {}
112
106
  post_install_message:
113
107
  rdoc_options: []
114
108
  require_paths:
115
109
  - lib
116
110
  required_ruby_version: !ruby/object:Gem::Requirement
117
- none: false
118
111
  requirements:
119
- - - ! '>='
112
+ - - '>='
120
113
  - !ruby/object:Gem::Version
121
114
  version: '0'
122
115
  required_rubygems_version: !ruby/object:Gem::Requirement
123
- none: false
124
116
  requirements:
125
- - - ! '>='
117
+ - - '>='
126
118
  - !ruby/object:Gem::Version
127
119
  version: '0'
128
120
  requirements: []
129
121
  rubyforge_project:
130
- rubygems_version: 1.8.23
122
+ rubygems_version: 2.0.0
131
123
  signing_key:
132
- specification_version: 3
124
+ specification_version: 4
133
125
  summary: A simple non destructive mocking library.
134
126
  test_files:
135
127
  - spec/spec_helper.rb