spy 0.4.3 → 1.0.2
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.
- 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:
|