spy 0.4.3 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.tool-versions +1 -0
- data/.travis.yml +7 -5
- data/CHANGELOG.md +12 -0
- data/README.md +3 -2
- data/Rakefile +1 -1
- data/lib/spy/api.rb +2 -2
- data/lib/spy/subroutine.rb +85 -21
- data/lib/spy/version.rb +1 -1
- data/lib/spy.rb +0 -2
- data/spy.gemspec +4 -3
- data/test/integration/test_constant_spying.rb +3 -3
- data/test/integration/test_instance_method.rb +6 -0
- data/test/integration/test_subroutine_spying.rb +2 -2
- data/test/spy/test_mock.rb +2 -2
- data/test/spy/test_subroutine.rb +129 -5
- data/test/support/pen.rb +21 -5
- data/test/test_helper.rb +4 -2
- metadata +24 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3906b9e65a981746a6dc4e51106ed64fc925478cb73335eb8a9d46ae9fc31931
|
4
|
+
data.tar.gz: 85e19b544c6ccb98616dd846db8263da3d0e8abcfd2158a5749d8988c5dc32e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57544c0872ff818dc065037e1e2a10c34b1edb698ad84ebf1e184aa190d24c8663d51d011619bb6a1024c93f1d94a03a8bd6578274605a56f0b0ba06aabf6abc
|
7
|
+
data.tar.gz: 43b7ca82d10759bb6083fdd76b27941425cefbcc63bc2b8a585b34d3c8e2c2659f24c1f4f32843ee1c1b8f3aee1d64c127fb769774430e77a31ea7005aeebbcb
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 2.7.0
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## Spy 1.0.1 (August 20th, 2020) ##
|
2
|
+
|
3
|
+
* Fix call_through w/ instance methods (@lreeves)
|
4
|
+
* Replace implicit Proc.new by explicit given block reference (@Hugo-Hache)
|
5
|
+
* Remove 2.7 warnings (@byroot)
|
6
|
+
|
7
|
+
## Spy 1.0.0 (October 10, 2018) ##
|
8
|
+
|
9
|
+
* drop support for ruby 1.9.3, 2.0. Only support 2.1+ (@dylanahsmith)
|
10
|
+
* support named arguments (@dylanahsmith)
|
11
|
+
* Fix readme (@ignat-z)
|
12
|
+
|
1
13
|
## Spy 0.4.3 (April 14, 2016) ##
|
2
14
|
|
3
15
|
* Double performance of spy lookups (@BlakeMesdag)
|
data/README.md
CHANGED
@@ -9,7 +9,8 @@
|
|
9
9
|
|
10
10
|
Spy is a lightweight stubbing framework with support for method spies, constant stubs, and object mocks.
|
11
11
|
|
12
|
-
Spy
|
12
|
+
Spy supports ruby 2.1.0+.
|
13
|
+
For versions less than 2.1 use v0.4.5
|
13
14
|
|
14
15
|
Spy features that were completed were tested against the rspec-mocks tests so it covers all cases that rspec-mocks does.
|
15
16
|
|
@@ -197,7 +198,7 @@ In your test file
|
|
197
198
|
```ruby
|
198
199
|
def test_title
|
199
200
|
book = Book.new
|
200
|
-
title_spy = Spy.on(book, title)
|
201
|
+
title_spy = Spy.on(book, :title)
|
201
202
|
book.title
|
202
203
|
book.title
|
203
204
|
|
data/Rakefile
CHANGED
data/lib/spy/api.rb
CHANGED
data/lib/spy/subroutine.rb
CHANGED
@@ -32,6 +32,8 @@ module Spy
|
|
32
32
|
def initialize(object, method_name, singleton_method = true)
|
33
33
|
@base_object, @method_name = object, method_name
|
34
34
|
@singleton_method = singleton_method
|
35
|
+
@plan = nil
|
36
|
+
@call_through = false
|
35
37
|
reset!
|
36
38
|
end
|
37
39
|
|
@@ -51,8 +53,21 @@ module Spy
|
|
51
53
|
@original_method = current_method
|
52
54
|
end
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
+
if original_method && original_method.owner == base_object
|
57
|
+
original_method.owner.send(:remove_method, method_name)
|
58
|
+
end
|
59
|
+
|
60
|
+
if singleton_method
|
61
|
+
if base_object.singleton_class.method_defined?(method_name) || base_object.singleton_class.private_method_defined?(method_name)
|
62
|
+
base_object.singleton_class.send(:alias_method, method_name, method_name)
|
63
|
+
end
|
64
|
+
base_object.define_singleton_method(method_name, override_method)
|
65
|
+
else
|
66
|
+
if base_object.method_defined?(method_name) || base_object.private_method_defined?(method_name)
|
67
|
+
base_object.send(:alias_method, method_name, method_name)
|
68
|
+
end
|
69
|
+
base_object.send(:define_method, method_name, override_method)
|
70
|
+
end
|
56
71
|
|
57
72
|
if [:public, :protected, :private].include? hook_opts[:visibility]
|
58
73
|
method_owner.send(hook_opts[:visibility], method_name)
|
@@ -68,11 +83,10 @@ module Spy
|
|
68
83
|
def unhook
|
69
84
|
raise NeverHookedError, "'#{method_name}' method has not been hooked" unless hooked?
|
70
85
|
|
86
|
+
method_owner.send(:remove_method, method_name)
|
71
87
|
if original_method && method_owner == original_method.owner
|
72
|
-
|
73
|
-
|
74
|
-
else
|
75
|
-
method_owner.send(:remove_method, method_name)
|
88
|
+
original_method.owner.send(:define_method, method_name, original_method)
|
89
|
+
original_method.owner.send(original_method_visibility, method_name) if original_method_visibility
|
76
90
|
end
|
77
91
|
|
78
92
|
clear_method!
|
@@ -104,7 +118,7 @@ module Spy
|
|
104
118
|
# spy.and_return(force: true) { |invalid_arity| true }
|
105
119
|
#
|
106
120
|
# @return [self]
|
107
|
-
def and_return(value = nil)
|
121
|
+
def and_return(value = nil, &block)
|
108
122
|
@do_not_check_plan_arity = false
|
109
123
|
|
110
124
|
if block_given?
|
@@ -114,7 +128,7 @@ module Spy
|
|
114
128
|
raise ArgumentError, "value and block conflict. Choose one"
|
115
129
|
end
|
116
130
|
|
117
|
-
@plan =
|
131
|
+
@plan = block
|
118
132
|
check_for_too_many_arguments!(@plan)
|
119
133
|
else
|
120
134
|
@plan = Proc.new { value }
|
@@ -135,13 +149,8 @@ module Spy
|
|
135
149
|
# tells the spy to call the original method
|
136
150
|
# @return [self]
|
137
151
|
def and_call_through
|
138
|
-
@
|
139
|
-
|
140
|
-
original_method.call(*args, &block)
|
141
|
-
else
|
142
|
-
base_object.send(:method_missing, method_name, *args, &block)
|
143
|
-
end
|
144
|
-
end
|
152
|
+
@call_through = true
|
153
|
+
|
145
154
|
self
|
146
155
|
end
|
147
156
|
|
@@ -167,6 +176,7 @@ module Spy
|
|
167
176
|
end
|
168
177
|
|
169
178
|
@plan = Proc.new { raise exception }
|
179
|
+
self
|
170
180
|
end
|
171
181
|
|
172
182
|
# @overload and_throw(symbol)
|
@@ -191,9 +201,9 @@ module Spy
|
|
191
201
|
# check if the method was called with the exact arguments
|
192
202
|
# @param args Arguments that should have been sent to the method
|
193
203
|
# @return [Boolean]
|
194
|
-
def has_been_called_with?(*args)
|
204
|
+
def has_been_called_with?(*args, &block)
|
195
205
|
raise NeverHookedError unless @was_hooked
|
196
|
-
match = block_given? ?
|
206
|
+
match = block_given? ? block : proc { |call| call.args == args }
|
197
207
|
calls.any?(&match)
|
198
208
|
end
|
199
209
|
|
@@ -201,10 +211,18 @@ module Spy
|
|
201
211
|
# method.
|
202
212
|
def invoke(object, args, block, called_from)
|
203
213
|
check_arity!(args.size)
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
214
|
+
|
215
|
+
result =
|
216
|
+
if @call_through
|
217
|
+
call_plan(build_call_through_plan(object), block, *args)
|
218
|
+
elsif @plan
|
219
|
+
check_for_too_many_arguments!(@plan)
|
220
|
+
if base_object.is_a? Class
|
221
|
+
call_plan(@plan, block, object, *args)
|
222
|
+
else
|
223
|
+
call_plan(@plan, block, *args)
|
224
|
+
end
|
225
|
+
end
|
208
226
|
ensure
|
209
227
|
calls << CallLog.new(object, called_from, args, block, result)
|
210
228
|
end
|
@@ -272,6 +290,8 @@ module Spy
|
|
272
290
|
min_arity = block.arity
|
273
291
|
min_arity = min_arity.abs - 1 if min_arity < 0
|
274
292
|
|
293
|
+
min_arity -=1 if base_object.is_a? Class # Instance-method procs take an extra param for receiving object
|
294
|
+
|
275
295
|
if min_arity > arity_range.max
|
276
296
|
raise ArgumentError.new("block requires #{min_arity} arguments while original_method require a maximum of #{arity_range.max}")
|
277
297
|
end
|
@@ -281,6 +301,8 @@ module Spy
|
|
281
301
|
@arity_range ||=
|
282
302
|
if original_method
|
283
303
|
min = max = 0
|
304
|
+
key_args = false
|
305
|
+
opt_keys = false
|
284
306
|
original_method.parameters.each do |type,_|
|
285
307
|
case type
|
286
308
|
when :req
|
@@ -290,8 +312,17 @@ module Spy
|
|
290
312
|
max += 1
|
291
313
|
when :rest
|
292
314
|
max = Float::INFINITY
|
315
|
+
when :keyreq
|
316
|
+
key_args = true
|
317
|
+
when :keyrest, :key
|
318
|
+
key_args = true
|
319
|
+
opt_keys = true
|
293
320
|
end
|
294
321
|
end
|
322
|
+
if key_args
|
323
|
+
max += 1
|
324
|
+
min += 1 unless opt_keys
|
325
|
+
end
|
295
326
|
(min..max)
|
296
327
|
end
|
297
328
|
end
|
@@ -304,6 +335,39 @@ module Spy
|
|
304
335
|
@method_owner ||= current_method.owner
|
305
336
|
end
|
306
337
|
|
338
|
+
def build_call_through_plan(object)
|
339
|
+
if original_method
|
340
|
+
if @base_object.is_a?(Class) && original_method.is_a?(UnboundMethod)
|
341
|
+
original_method.bind(object)
|
342
|
+
else
|
343
|
+
original_method
|
344
|
+
end
|
345
|
+
else
|
346
|
+
Proc.new do |*args, &block|
|
347
|
+
base_object.send(:method_missing, method_name, *args, &block)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
def call_plan(plan, block, *args)
|
353
|
+
if ruby_27_last_arg_hash?(args)
|
354
|
+
*prefix, last = args
|
355
|
+
plan.call(*prefix, **last, &block)
|
356
|
+
else
|
357
|
+
plan.call(*args, &block)
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
# Ruby 2.7 gives a deprecation warning about passing hash as last argument for a method
|
362
|
+
# with a double-splat operator (**), and Ruby 3 raises an ArgumentError exception.
|
363
|
+
# This checks if args has a hash as last element to extract it and pass it with double-splat to avoid an exception.
|
364
|
+
def ruby_27_last_arg_hash?(args)
|
365
|
+
last = args.last
|
366
|
+
last.instance_of?(Hash) &&
|
367
|
+
!last.empty? &&
|
368
|
+
Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.0")
|
369
|
+
end
|
370
|
+
|
307
371
|
class << self
|
308
372
|
|
309
373
|
# retrieve the method spy from an object or create a new one
|
data/lib/spy/version.rb
CHANGED
data/lib/spy.rb
CHANGED
data/spy.gemspec
CHANGED
@@ -6,12 +6,12 @@ require 'spy/version'
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
gem.name = "spy"
|
8
8
|
gem.version = Spy::VERSION
|
9
|
-
gem.required_ruby_version = '>= 1.
|
9
|
+
gem.required_ruby_version = '>= 2.1.0'
|
10
10
|
gem.license = 'MIT'
|
11
11
|
gem.authors = ["Ryan Ong"]
|
12
12
|
gem.email = ["ryanong@gmail.com"]
|
13
13
|
gem.summary = %q{A simple modern mocking library that uses the spy pattern and checks method's existence and arity.}
|
14
|
-
gem.description = %q{Spy is a mocking library that was made for the modern age. It supports only 1.
|
14
|
+
gem.description = %q{Spy is a mocking library that was made for the modern age. It supports only 2.1.0+. Spy by default will raise an error if you attempt to stub a method that doesn't exist or call the stubbed method with the wrong arity.}
|
15
15
|
gem.homepage = "https://github.com/ryanong/spy"
|
16
16
|
|
17
17
|
gem.files = `git ls-files`.split($/)
|
@@ -19,8 +19,9 @@ Gem::Specification.new do |gem|
|
|
19
19
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
20
|
gem.require_paths = ["lib"]
|
21
21
|
gem.add_development_dependency('pry')
|
22
|
-
gem.add_development_dependency('pry-
|
22
|
+
gem.add_development_dependency('pry-byebug')
|
23
23
|
gem.add_development_dependency('minitest', '>= 4.5.0')
|
24
|
+
gem.add_development_dependency('minitest-reporters')
|
24
25
|
gem.add_development_dependency('rspec-core')
|
25
26
|
gem.add_development_dependency('rspec-expectations')
|
26
27
|
gem.add_development_dependency('coveralls')
|
@@ -30,7 +30,7 @@ class TestConstantSpying < Minitest::Test
|
|
30
30
|
assert_equal "hello world", Foo.hello
|
31
31
|
|
32
32
|
spy = Spy.on_const(Foo, :HELLO)
|
33
|
-
|
33
|
+
assert_nil Foo.hello
|
34
34
|
spy.and_return("awesome")
|
35
35
|
assert_equal "awesome", Foo.hello
|
36
36
|
|
@@ -39,7 +39,7 @@ class TestConstantSpying < Minitest::Test
|
|
39
39
|
|
40
40
|
assert_equal "hello world", Foo::Bar.hello
|
41
41
|
spy = Spy.on_const(Foo, :HELLO)
|
42
|
-
|
42
|
+
assert_nil Foo::Bar.hello
|
43
43
|
spy.and_return("awesome")
|
44
44
|
assert_equal "awesome", Foo::Bar.hello
|
45
45
|
|
@@ -48,7 +48,7 @@ class TestConstantSpying < Minitest::Test
|
|
48
48
|
|
49
49
|
assert_equal "hello world", ChildFoo.hello
|
50
50
|
spy = Spy.on_const(Foo, :HELLO)
|
51
|
-
|
51
|
+
assert_nil ChildFoo.hello
|
52
52
|
spy.and_return("awesome")
|
53
53
|
assert_equal "awesome", ChildFoo.hello
|
54
54
|
|
@@ -17,6 +17,12 @@ class TestAnyInstanceOf < Minitest::Test
|
|
17
17
|
Spy::Agency.instance.dissolve!
|
18
18
|
end
|
19
19
|
|
20
|
+
def test_call_through_with_instance_method
|
21
|
+
Spy.on_instance_method(Foo, :bar).and_call_through
|
22
|
+
assert_equal "foobar", Foo.new.bar
|
23
|
+
Spy.off_instance_method(Foo, :bar)
|
24
|
+
end
|
25
|
+
|
20
26
|
def test_it_overides_all_methods
|
21
27
|
assert_equal Foo.new.bar, "foobar"
|
22
28
|
spy = Spy.on_instance_method(Foo, bar: "timshel")
|
@@ -16,12 +16,12 @@ class TestSpy < Minitest::Test
|
|
16
16
|
|
17
17
|
assert_kind_of Spy::Subroutine, pen_write_spy
|
18
18
|
assert_kind_of Spy::Subroutine, pen_write_hello_spy
|
19
|
-
assert_equal [pen_write_spy, pen_write_hello_spy], Spy::Agency.instance.
|
19
|
+
assert_equal [pen_write_spy, pen_write_hello_spy], Spy::Agency.instance.spies
|
20
20
|
assert pen_write_spy.has_been_called?
|
21
21
|
assert pen_write_hello_spy.has_been_called?
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
24
|
+
def test_spy_on_hooks_and_saves_spy_with_hash
|
25
25
|
pen_write_spy, pen_write_hello_spy = Spy.on(@pen, write: "hello", write_hello: "world")
|
26
26
|
assert_equal "hello", @pen.write(nil)
|
27
27
|
assert_equal "world", @pen.write_hello
|
data/test/spy/test_mock.rb
CHANGED
@@ -68,6 +68,7 @@ module Spy
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
BUGGY_METHODS = %i(tap pretty_print_inspect trust untrust untrusted? debugger byebug taint untaint tainted?)
|
71
72
|
def test_mocked_methods
|
72
73
|
pen_methods = Pen.public_instance_methods(false) +
|
73
74
|
Pen.protected_instance_methods(false) +
|
@@ -76,8 +77,7 @@ module Spy
|
|
76
77
|
assert_equal pen_methods.sort, @pen_mock.mocked_methods.sort
|
77
78
|
end
|
78
79
|
|
79
|
-
|
80
|
-
methods_to_test = Object.instance_methods - buggy_methods
|
80
|
+
methods_to_test = Object.instance_methods - BUGGY_METHODS
|
81
81
|
methods_to_test.each do |method_name|
|
82
82
|
object_method = Object.instance_method(method_name)
|
83
83
|
if object_method.arity == 0 || (RUBY_ENGINE != "jruby" && object_method.parameters == [])
|
data/test/spy/test_subroutine.rb
CHANGED
@@ -6,6 +6,10 @@ module Spy
|
|
6
6
|
Subroutine.new(base_object, method_name).hook
|
7
7
|
end
|
8
8
|
|
9
|
+
def spy_on_instance_method(base_object, method_name)
|
10
|
+
Subroutine.new(base_object, method_name, false).hook
|
11
|
+
end
|
12
|
+
|
9
13
|
def setup
|
10
14
|
@pen = Pen.new
|
11
15
|
end
|
@@ -40,13 +44,13 @@ module Spy
|
|
40
44
|
end
|
41
45
|
|
42
46
|
def test_spy_can_hook_and_record_a_meta_method_call_on_a_constant
|
43
|
-
assert_equal "
|
44
|
-
meta_spy = spy_on(Pen, :
|
47
|
+
assert_equal "meta_class_method", Pen.meta_class_method
|
48
|
+
meta_spy = spy_on(Pen, :meta_class_method)
|
45
49
|
refute meta_spy.has_been_called?
|
46
|
-
assert_nil Pen.
|
50
|
+
assert_nil Pen.meta_class_method
|
47
51
|
assert meta_spy.has_been_called?
|
48
52
|
meta_spy.unhook
|
49
|
-
assert_equal "
|
53
|
+
assert_equal "meta_class_method", Pen.meta_class_method
|
50
54
|
end
|
51
55
|
|
52
56
|
def test_spy_can_hook_record_and_unhook_a_meta_method
|
@@ -86,6 +90,18 @@ module Spy
|
|
86
90
|
assert_equal result, @pen.write(nil)
|
87
91
|
end
|
88
92
|
|
93
|
+
def test_spy_and_raise_raises_the_set_exception
|
94
|
+
pen_write_spy = spy_on(@pen, :write).and_raise(ArgumentError, "problems!")
|
95
|
+
assert_kind_of Subroutine, pen_write_spy
|
96
|
+
assert_equal [pen_write_spy], Agency.instance.spies
|
97
|
+
|
98
|
+
e = assert_raises ArgumentError do
|
99
|
+
@pen.write(nil)
|
100
|
+
end
|
101
|
+
assert_equal "problems!", e.message
|
102
|
+
assert pen_write_spy.has_been_called?
|
103
|
+
end
|
104
|
+
|
89
105
|
def test_spy_and_return_can_call_a_block
|
90
106
|
result = "hello world"
|
91
107
|
|
@@ -97,6 +113,15 @@ module Spy
|
|
97
113
|
assert_empty @pen.written
|
98
114
|
end
|
99
115
|
|
116
|
+
def test_spy_and_return_can_call_a_block_with_hash
|
117
|
+
result = "hello world"
|
118
|
+
|
119
|
+
spy_on(@pen, :write_hash).and_return { |**opts| opts[:test] }
|
120
|
+
|
121
|
+
assert_equal result, @pen.write_hash(test: result)
|
122
|
+
assert_empty @pen.written
|
123
|
+
end
|
124
|
+
|
100
125
|
def test_spy_and_return_can_call_a_block_raises_when_there_is_an_arity_mismatch
|
101
126
|
write_spy = spy_on(@pen, :write)
|
102
127
|
write_spy.and_return do |*args|
|
@@ -125,6 +150,73 @@ module Spy
|
|
125
150
|
assert_equal string, result
|
126
151
|
end
|
127
152
|
|
153
|
+
def test_spy_and_call_through_returns_original_method_result
|
154
|
+
string = "hello world"
|
155
|
+
|
156
|
+
write_spy = spy_on(@pen, :write).and_call_through
|
157
|
+
another_spy = spy_on(@pen, :another).and_call_through
|
158
|
+
|
159
|
+
result = @pen.write(string)
|
160
|
+
|
161
|
+
assert_equal string, result
|
162
|
+
assert write_spy.has_been_called?
|
163
|
+
assert_equal 'another', @pen.another
|
164
|
+
assert another_spy.has_been_called?
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_spy_and_call_through_with_hash_original_method
|
168
|
+
string = 'test:hello world'
|
169
|
+
|
170
|
+
write_spy = spy_on(@pen, :write_hash).and_call_through
|
171
|
+
|
172
|
+
@pen.write_hash(test: 'hello world')
|
173
|
+
assert_equal string, @pen.written.last
|
174
|
+
assert write_spy.has_been_called?
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_spy_on_instance_and_call_through_returns_original_method_result
|
178
|
+
string = "hello world"
|
179
|
+
|
180
|
+
inst_write_spy = spy_on_instance_method(Pen, :write).and_call_through
|
181
|
+
inst_another_spy = spy_on_instance_method(Pen, :another).and_call_through
|
182
|
+
|
183
|
+
result = @pen.write(string)
|
184
|
+
|
185
|
+
assert_equal string, result
|
186
|
+
assert inst_write_spy.has_been_called?
|
187
|
+
assert_equal 'another', @pen.another
|
188
|
+
assert inst_another_spy.has_been_called?
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_spy_on_instance_and_call_through_with_hash
|
192
|
+
string = 'test:hello world'
|
193
|
+
|
194
|
+
inst_write_spy = spy_on_instance_method(Pen, :write_hash).and_call_through
|
195
|
+
|
196
|
+
@pen.write_hash(test: 'hello world')
|
197
|
+
|
198
|
+
assert_equal string, @pen.written.last
|
199
|
+
assert inst_write_spy.has_been_called?
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_spy_on_instance_and_call_through_to_aryable
|
203
|
+
to_aryable = Class.new do
|
204
|
+
def hello
|
205
|
+
'hello'
|
206
|
+
end
|
207
|
+
|
208
|
+
def to_ary
|
209
|
+
[1]
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
inst_hello_spy = spy_on_instance_method(to_aryable, :hello).and_call_through
|
214
|
+
inst = to_aryable.new
|
215
|
+
|
216
|
+
assert_equal 'hello', inst.hello
|
217
|
+
assert inst_hello_spy.has_been_called?
|
218
|
+
end
|
219
|
+
|
128
220
|
def test_spy_hook_records_number_of_calls
|
129
221
|
pen_write_spy = spy_on(@pen, :write)
|
130
222
|
assert_equal 0, pen_write_spy.calls.size
|
@@ -145,7 +237,7 @@ module Spy
|
|
145
237
|
assert pen_write_spy.has_been_called_with?("hello")
|
146
238
|
end
|
147
239
|
|
148
|
-
def
|
240
|
+
def test_spy_hook_records_number_of_calls2
|
149
241
|
args = ["hello world"]
|
150
242
|
block = Proc.new {}
|
151
243
|
pen_write_spy = spy_on(@pen, :write)
|
@@ -187,6 +279,38 @@ module Spy
|
|
187
279
|
end
|
188
280
|
end
|
189
281
|
|
282
|
+
def test_that_method_spy_keeps_arity_with_optional_keyword_args
|
283
|
+
spy_on(@pen, :opt_kwargs)
|
284
|
+
@pen.opt_kwargs(:pos1)
|
285
|
+
@pen.opt_kwargs(:pos1, opt: 1, opt2: 2)
|
286
|
+
assert_raises ArgumentError do
|
287
|
+
@pen.opt_kwargs
|
288
|
+
end
|
289
|
+
assert_raises ArgumentError do
|
290
|
+
@pen.opt_kwargs(:pos1, :pos2, opt: 1)
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def test_that_method_spy_keeps_arity_with_keyword_splat
|
295
|
+
spy_on(@pen, :keyrest)
|
296
|
+
@pen.keyrest
|
297
|
+
@pen.keyrest(a: 1, b: 2)
|
298
|
+
assert_raises ArgumentError do
|
299
|
+
@pen.keyrest(:pos1, :pos2)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def test_that_method_spy_keeps_arity_with_required_keyword_args
|
304
|
+
spy_on(@pen, :req_kwargs)
|
305
|
+
@pen.req_kwargs(req1: 1, req2: 2)
|
306
|
+
assert_raises ArgumentError do
|
307
|
+
@pen.req_kwargs
|
308
|
+
end
|
309
|
+
assert_raises ArgumentError do
|
310
|
+
@pen.req_kwargs(:pos1, :pos2)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
190
314
|
def test_hook_mimics_public_visibility
|
191
315
|
spy_on(@pen, :public_method)
|
192
316
|
assert @pen.singleton_class.public_method_defined? :public_method
|
data/test/support/pen.rb
CHANGED
@@ -27,6 +27,12 @@ class Pen
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
def write_hash(**params)
|
31
|
+
params.each do |p|
|
32
|
+
write(p.join(':'))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
30
36
|
def greet(hello = "hello", name)
|
31
37
|
write("#{hello} #{name}")
|
32
38
|
end
|
@@ -38,6 +44,18 @@ class Pen
|
|
38
44
|
"another"
|
39
45
|
end
|
40
46
|
|
47
|
+
def opt_kwargs(required, opt: nil, opt2: nil)
|
48
|
+
[required, opt: opt, opt2: opt2]
|
49
|
+
end
|
50
|
+
|
51
|
+
def keyrest(**kwargs)
|
52
|
+
kwargs
|
53
|
+
end
|
54
|
+
|
55
|
+
def req_kwargs(req1:, req2:)
|
56
|
+
[req1, req2]
|
57
|
+
end
|
58
|
+
|
41
59
|
protected
|
42
60
|
def protected_method
|
43
61
|
end
|
@@ -65,13 +83,11 @@ class Pen
|
|
65
83
|
end
|
66
84
|
end
|
67
85
|
|
68
|
-
|
69
|
-
|
70
|
-
Pen.define_singleton_method(:meta_method) do
|
71
|
-
another
|
86
|
+
Pen.define_singleton_method(:meta_class_method) do
|
87
|
+
"meta_class_method".freeze
|
72
88
|
end
|
73
89
|
|
74
90
|
Pen.send(:define_method, :meta_method) do
|
75
|
-
|
91
|
+
"meta_method".freeze
|
76
92
|
end
|
77
93
|
|
data/test/test_helper.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'bundler/setup'
|
2
|
-
require 'minitest/autorun'
|
3
2
|
require 'pry'
|
4
|
-
require 'pry-
|
3
|
+
require 'pry-byebug'
|
4
|
+
require 'minitest/autorun'
|
5
|
+
require "minitest/reporters"
|
5
6
|
require 'coveralls'
|
6
7
|
Coveralls.wear!
|
8
|
+
Minitest::Reporters.use!
|
7
9
|
|
8
10
|
require 'spy'
|
9
11
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Ong
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: pry-
|
28
|
+
name: pry-byebug
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 4.5.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest-reporters
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rspec-core
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,7 +109,7 @@ dependencies:
|
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '0'
|
97
111
|
description: Spy is a mocking library that was made for the modern age. It supports
|
98
|
-
only 1.
|
112
|
+
only 2.1.0+. Spy by default will raise an error if you attempt to stub a method
|
99
113
|
that doesn't exist or call the stubbed method with the wrong arity.
|
100
114
|
email:
|
101
115
|
- ryanong@gmail.com
|
@@ -104,6 +118,7 @@ extensions: []
|
|
104
118
|
extra_rdoc_files: []
|
105
119
|
files:
|
106
120
|
- ".gitignore"
|
121
|
+
- ".tool-versions"
|
107
122
|
- ".travis.yml"
|
108
123
|
- ".yardopts"
|
109
124
|
- CHANGELOG.md
|
@@ -154,7 +169,7 @@ homepage: https://github.com/ryanong/spy
|
|
154
169
|
licenses:
|
155
170
|
- MIT
|
156
171
|
metadata: {}
|
157
|
-
post_install_message:
|
172
|
+
post_install_message:
|
158
173
|
rdoc_options: []
|
159
174
|
require_paths:
|
160
175
|
- lib
|
@@ -162,16 +177,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
162
177
|
requirements:
|
163
178
|
- - ">="
|
164
179
|
- !ruby/object:Gem::Version
|
165
|
-
version: 1.
|
180
|
+
version: 2.1.0
|
166
181
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
182
|
requirements:
|
168
183
|
- - ">="
|
169
184
|
- !ruby/object:Gem::Version
|
170
185
|
version: '0'
|
171
186
|
requirements: []
|
172
|
-
|
173
|
-
|
174
|
-
signing_key:
|
187
|
+
rubygems_version: 3.1.2
|
188
|
+
signing_key:
|
175
189
|
specification_version: 4
|
176
190
|
summary: A simple modern mocking library that uses the spy pattern and checks method's
|
177
191
|
existence and arity.
|
@@ -201,4 +215,3 @@ test_files:
|
|
201
215
|
- test/spy/test_subroutine.rb
|
202
216
|
- test/support/pen.rb
|
203
217
|
- test/test_helper.rb
|
204
|
-
has_rdoc:
|