spy 0.4.1 → 1.0.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.
- checksums.yaml +5 -5
- data/.tool-versions +1 -0
- data/.travis.yml +7 -5
- data/CHANGELOG.md +24 -0
- data/README.md +3 -2
- data/Rakefile +1 -1
- data/lib/spy.rb +0 -2
- data/lib/spy/api.rb +2 -2
- data/lib/spy/integration.rb +4 -2
- data/lib/spy/subroutine.rb +79 -24
- data/lib/spy/version.rb +1 -1
- data/spy.gemspec +5 -4
- data/test/integration/test_api.rb +1 -1
- data/test/integration/test_constant_spying.rb +4 -4
- data/test/integration/test_instance_method.rb +7 -1
- data/test/integration/test_mocking.rb +1 -1
- data/test/integration/test_subroutine_spying.rb +3 -3
- data/test/spy/test_mock.rb +3 -3
- data/test/spy/test_subroutine.rb +50 -6
- data/test/support/pen.rb +15 -5
- data/test/test_helper.rb +4 -2
- metadata +42 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: aa89505674a7286f055ee019988cf29debbdd5cb7e525a022864f551d20ae842
|
4
|
+
data.tar.gz: fa61fa5e78f5aea6fab75bcc471bdcc8032182d8e9c7528e9370b91022ef7ae0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: abb91b0bcef139e03b90cb59f2f1b5d9f0c52c8137beafab301f56a96d44dbcffc203bcf0c69cd7e5376bed68549e0bb9bf407b4f85e07fc91d875d401ce39d0
|
7
|
+
data.tar.gz: 58d355373220b031ba5740b0cfdc2a6d9bb94a7c39166fafae23896342eec3c3b907994f7224e80abc7f2d1ae289048d98cd56a05750569befa62c98f6330a22
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 2.7.0
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,27 @@
|
|
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
|
+
|
13
|
+
## Spy 0.4.3 (April 14, 2016) ##
|
14
|
+
|
15
|
+
* Double performance of spy lookups (@BlakeMesdag)
|
16
|
+
|
17
|
+
## Spy 0.4.2 ##
|
18
|
+
|
19
|
+
* Support for minitest 5.1
|
20
|
+
|
21
|
+
## Spy 0.4.1 ##
|
22
|
+
|
23
|
+
* Support for minitest 5.0
|
24
|
+
|
1
25
|
## Spy 0.4.0 (May 8, 2013) ##
|
2
26
|
|
3
27
|
* Allow `Spy#have_received_with` to accept a block
|
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.rb
CHANGED
data/lib/spy/api.rb
CHANGED
data/lib/spy/integration.rb
CHANGED
@@ -10,9 +10,11 @@ module Spy
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
if defined?(::MiniTest::Unit::TestCase)
|
13
|
+
if defined?(::MiniTest::Unit::TestCase) && !::MiniTest::Unit::TestCase.include?(MiniTestAdapter)
|
14
14
|
::MiniTest::Unit::TestCase.send(:include, MiniTestAdapter)
|
15
|
-
|
15
|
+
end
|
16
|
+
|
17
|
+
if defined?(::Minitest::Test) && !::Minitest::Test.include?(MiniTestAdapter)
|
16
18
|
::Minitest::Test.send(:include, MiniTestAdapter)
|
17
19
|
end
|
18
20
|
end
|
data/lib/spy/subroutine.rb
CHANGED
@@ -32,6 +32,7 @@ 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
|
35
36
|
reset!
|
36
37
|
end
|
37
38
|
|
@@ -51,8 +52,21 @@ module Spy
|
|
51
52
|
@original_method = current_method
|
52
53
|
end
|
53
54
|
|
54
|
-
|
55
|
-
|
55
|
+
if original_method && original_method.owner == base_object
|
56
|
+
original_method.owner.send(:remove_method, method_name)
|
57
|
+
end
|
58
|
+
|
59
|
+
if singleton_method
|
60
|
+
if base_object.singleton_class.method_defined?(method_name) || base_object.singleton_class.private_method_defined?(method_name)
|
61
|
+
base_object.singleton_class.alias_method(method_name, method_name)
|
62
|
+
end
|
63
|
+
base_object.define_singleton_method(method_name, override_method)
|
64
|
+
else
|
65
|
+
if base_object.method_defined?(method_name) || base_object.private_method_defined?(method_name)
|
66
|
+
base_object.alias_method(method_name, method_name)
|
67
|
+
end
|
68
|
+
base_object.define_method(method_name, override_method)
|
69
|
+
end
|
56
70
|
|
57
71
|
if [:public, :protected, :private].include? hook_opts[:visibility]
|
58
72
|
method_owner.send(hook_opts[:visibility], method_name)
|
@@ -68,11 +82,10 @@ module Spy
|
|
68
82
|
def unhook
|
69
83
|
raise NeverHookedError, "'#{method_name}' method has not been hooked" unless hooked?
|
70
84
|
|
85
|
+
method_owner.send(:remove_method, method_name)
|
71
86
|
if original_method && method_owner == original_method.owner
|
72
|
-
|
73
|
-
|
74
|
-
else
|
75
|
-
method_owner.send(:remove_method, method_name)
|
87
|
+
original_method.owner.send(:define_method, method_name, original_method)
|
88
|
+
original_method.owner.send(original_method_visibility, method_name) if original_method_visibility
|
76
89
|
end
|
77
90
|
|
78
91
|
clear_method!
|
@@ -104,7 +117,7 @@ module Spy
|
|
104
117
|
# spy.and_return(force: true) { |invalid_arity| true }
|
105
118
|
#
|
106
119
|
# @return [self]
|
107
|
-
def and_return(value = nil)
|
120
|
+
def and_return(value = nil, &block)
|
108
121
|
@do_not_check_plan_arity = false
|
109
122
|
|
110
123
|
if block_given?
|
@@ -114,7 +127,7 @@ module Spy
|
|
114
127
|
raise ArgumentError, "value and block conflict. Choose one"
|
115
128
|
end
|
116
129
|
|
117
|
-
@plan =
|
130
|
+
@plan = block
|
118
131
|
check_for_too_many_arguments!(@plan)
|
119
132
|
else
|
120
133
|
@plan = Proc.new { value }
|
@@ -135,13 +148,29 @@ module Spy
|
|
135
148
|
# tells the spy to call the original method
|
136
149
|
# @return [self]
|
137
150
|
def and_call_through
|
138
|
-
@
|
139
|
-
|
140
|
-
original_method
|
141
|
-
|
142
|
-
|
151
|
+
if @base_object.is_a? Class
|
152
|
+
@plan = Proc.new do |object, *args, &block|
|
153
|
+
if original_method
|
154
|
+
if original_method.is_a? UnboundMethod
|
155
|
+
bound_method = original_method.bind(object)
|
156
|
+
bound_method.call(*args, &block)
|
157
|
+
else
|
158
|
+
original_method.call(*args, &block)
|
159
|
+
end
|
160
|
+
else
|
161
|
+
base_object.send(:method_missing, method_name, *args, &block)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
else
|
165
|
+
@plan = Proc.new do |*args, &block|
|
166
|
+
if original_method
|
167
|
+
original_method.call(*args, &block)
|
168
|
+
else
|
169
|
+
base_object.send(:method_missing, method_name, *args, &block)
|
170
|
+
end
|
143
171
|
end
|
144
172
|
end
|
173
|
+
|
145
174
|
self
|
146
175
|
end
|
147
176
|
|
@@ -167,6 +196,7 @@ module Spy
|
|
167
196
|
end
|
168
197
|
|
169
198
|
@plan = Proc.new { raise exception }
|
199
|
+
self
|
170
200
|
end
|
171
201
|
|
172
202
|
# @overload and_throw(symbol)
|
@@ -191,9 +221,9 @@ module Spy
|
|
191
221
|
# check if the method was called with the exact arguments
|
192
222
|
# @param args Arguments that should have been sent to the method
|
193
223
|
# @return [Boolean]
|
194
|
-
def has_been_called_with?(*args)
|
224
|
+
def has_been_called_with?(*args, &block)
|
195
225
|
raise NeverHookedError unless @was_hooked
|
196
|
-
match = block_given? ?
|
226
|
+
match = block_given? ? block : proc { |call| call.args == args }
|
197
227
|
calls.any?(&match)
|
198
228
|
end
|
199
229
|
|
@@ -201,10 +231,18 @@ module Spy
|
|
201
231
|
# method.
|
202
232
|
def invoke(object, args, block, called_from)
|
203
233
|
check_arity!(args.size)
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
234
|
+
|
235
|
+
if base_object.is_a? Class
|
236
|
+
result = if @plan
|
237
|
+
check_for_too_many_arguments!(@plan)
|
238
|
+
@plan.call(object, *args, &block)
|
239
|
+
end
|
240
|
+
else
|
241
|
+
result = if @plan
|
242
|
+
check_for_too_many_arguments!(@plan)
|
243
|
+
@plan.call(*args, &block)
|
244
|
+
end
|
245
|
+
end
|
208
246
|
ensure
|
209
247
|
calls << CallLog.new(object, called_from, args, block, result)
|
210
248
|
end
|
@@ -222,11 +260,12 @@ module Spy
|
|
222
260
|
# this returns a lambda that calls the spy object.
|
223
261
|
# we use eval to set the spy object id as a parameter so it can be extracted
|
224
262
|
# and looked up later using `Method#parameters`
|
263
|
+
SPY_ARGS_PREFIX='__spy_args_'.freeze
|
225
264
|
def override_method
|
226
265
|
eval <<-METHOD, binding, __FILE__, __LINE__ + 1
|
227
266
|
__method_spy__ = self
|
228
|
-
lambda do
|
229
|
-
__method_spy__.invoke(self,
|
267
|
+
lambda do |*#{SPY_ARGS_PREFIX}#{self.object_id}, &block|
|
268
|
+
__method_spy__.invoke(self, #{SPY_ARGS_PREFIX}#{self.object_id}, block, caller(1)[0])
|
230
269
|
end
|
231
270
|
METHOD
|
232
271
|
end
|
@@ -271,6 +310,8 @@ module Spy
|
|
271
310
|
min_arity = block.arity
|
272
311
|
min_arity = min_arity.abs - 1 if min_arity < 0
|
273
312
|
|
313
|
+
min_arity -=1 if base_object.is_a? Class # Instance-method procs take an extra param for receiving object
|
314
|
+
|
274
315
|
if min_arity > arity_range.max
|
275
316
|
raise ArgumentError.new("block requires #{min_arity} arguments while original_method require a maximum of #{arity_range.max}")
|
276
317
|
end
|
@@ -280,6 +321,8 @@ module Spy
|
|
280
321
|
@arity_range ||=
|
281
322
|
if original_method
|
282
323
|
min = max = 0
|
324
|
+
key_args = false
|
325
|
+
opt_keys = false
|
283
326
|
original_method.parameters.each do |type,_|
|
284
327
|
case type
|
285
328
|
when :req
|
@@ -289,8 +332,17 @@ module Spy
|
|
289
332
|
max += 1
|
290
333
|
when :rest
|
291
334
|
max = Float::INFINITY
|
335
|
+
when :keyreq
|
336
|
+
key_args = true
|
337
|
+
when :keyrest, :key
|
338
|
+
key_args = true
|
339
|
+
opt_keys = true
|
292
340
|
end
|
293
341
|
end
|
342
|
+
if key_args
|
343
|
+
max += 1
|
344
|
+
min += 1 unless opt_keys
|
345
|
+
end
|
294
346
|
(min..max)
|
295
347
|
end
|
296
348
|
end
|
@@ -364,9 +416,12 @@ module Spy
|
|
364
416
|
|
365
417
|
# @private
|
366
418
|
def get_spy_id(method)
|
367
|
-
|
368
|
-
|
369
|
-
|
419
|
+
if method.parameters[0].is_a?(Array) && method.parameters[0][1]
|
420
|
+
raw_id = method.parameters[0][1].to_s
|
421
|
+
if raw_id.start_with?(SPY_ARGS_PREFIX)
|
422
|
+
raw_id[SPY_ARGS_PREFIX.length..-1].to_i
|
423
|
+
end
|
424
|
+
end
|
370
425
|
end
|
371
426
|
end
|
372
427
|
end
|
data/lib/spy/version.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
|
-
gem.
|
14
|
-
gem.
|
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 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')
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class TestConstantSpying <
|
3
|
+
class TestConstantSpying < Minitest::Test
|
4
4
|
|
5
5
|
class Foo
|
6
6
|
HELLO = "hello world"
|
@@ -30,7 +30,7 @@ class TestConstantSpying < MiniTest::Unit::TestCase
|
|
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::Unit::TestCase
|
|
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::Unit::TestCase
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class TestAnyInstanceOf <
|
3
|
+
class TestAnyInstanceOf < Minitest::Test
|
4
4
|
class Foo
|
5
5
|
def bar
|
6
6
|
"foobar"
|
@@ -17,6 +17,12 @@ class TestAnyInstanceOf < MiniTest::Unit::TestCase
|
|
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")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class TestSpy <
|
3
|
+
class TestSpy < Minitest::Test
|
4
4
|
def setup
|
5
5
|
@pen = Pen.new
|
6
6
|
end
|
@@ -16,12 +16,12 @@ class TestSpy < MiniTest::Unit::TestCase
|
|
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
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
module Spy
|
4
|
-
class TestMock <
|
4
|
+
class TestMock < Minitest::Test
|
5
5
|
class BluePen < Pen
|
6
6
|
def write_hello(other)
|
7
7
|
end
|
@@ -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
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
module Spy
|
4
|
-
class TestSubroutine <
|
4
|
+
class TestSubroutine < Minitest::Test
|
5
5
|
def spy_on(base_object, method_name)
|
6
6
|
Subroutine.new(base_object, method_name).hook
|
7
7
|
end
|
@@ -40,13 +40,13 @@ module Spy
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def test_spy_can_hook_and_record_a_meta_method_call_on_a_constant
|
43
|
-
assert_equal "
|
44
|
-
meta_spy = spy_on(Pen, :
|
43
|
+
assert_equal "meta_class_method", Pen.meta_class_method
|
44
|
+
meta_spy = spy_on(Pen, :meta_class_method)
|
45
45
|
refute meta_spy.has_been_called?
|
46
|
-
assert_nil Pen.
|
46
|
+
assert_nil Pen.meta_class_method
|
47
47
|
assert meta_spy.has_been_called?
|
48
48
|
meta_spy.unhook
|
49
|
-
assert_equal "
|
49
|
+
assert_equal "meta_class_method", Pen.meta_class_method
|
50
50
|
end
|
51
51
|
|
52
52
|
def test_spy_can_hook_record_and_unhook_a_meta_method
|
@@ -86,6 +86,18 @@ module Spy
|
|
86
86
|
assert_equal result, @pen.write(nil)
|
87
87
|
end
|
88
88
|
|
89
|
+
def test_spy_and_raise_raises_the_set_exception
|
90
|
+
pen_write_spy = spy_on(@pen, :write).and_raise(ArgumentError, "problems!")
|
91
|
+
assert_kind_of Subroutine, pen_write_spy
|
92
|
+
assert_equal [pen_write_spy], Agency.instance.spies
|
93
|
+
|
94
|
+
e = assert_raises ArgumentError do
|
95
|
+
@pen.write(nil)
|
96
|
+
end
|
97
|
+
assert_equal "problems!", e.message
|
98
|
+
assert pen_write_spy.has_been_called?
|
99
|
+
end
|
100
|
+
|
89
101
|
def test_spy_and_return_can_call_a_block
|
90
102
|
result = "hello world"
|
91
103
|
|
@@ -145,7 +157,7 @@ module Spy
|
|
145
157
|
assert pen_write_spy.has_been_called_with?("hello")
|
146
158
|
end
|
147
159
|
|
148
|
-
def
|
160
|
+
def test_spy_hook_records_number_of_calls2
|
149
161
|
args = ["hello world"]
|
150
162
|
block = Proc.new {}
|
151
163
|
pen_write_spy = spy_on(@pen, :write)
|
@@ -187,6 +199,38 @@ module Spy
|
|
187
199
|
end
|
188
200
|
end
|
189
201
|
|
202
|
+
def test_that_method_spy_keeps_arity_with_optional_keyword_args
|
203
|
+
spy_on(@pen, :opt_kwargs)
|
204
|
+
@pen.opt_kwargs(:pos1)
|
205
|
+
@pen.opt_kwargs(:pos1, opt: 1, opt2: 2)
|
206
|
+
assert_raises ArgumentError do
|
207
|
+
@pen.opt_kwargs
|
208
|
+
end
|
209
|
+
assert_raises ArgumentError do
|
210
|
+
@pen.opt_kwargs(:pos1, :pos2, opt: 1)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_that_method_spy_keeps_arity_with_keyword_splat
|
215
|
+
spy_on(@pen, :keyrest)
|
216
|
+
@pen.keyrest
|
217
|
+
@pen.keyrest(a: 1, b: 2)
|
218
|
+
assert_raises ArgumentError do
|
219
|
+
@pen.keyrest(:pos1, :pos2)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_that_method_spy_keeps_arity_with_required_keyword_args
|
224
|
+
spy_on(@pen, :req_kwargs)
|
225
|
+
@pen.req_kwargs(req1: 1, req2: 2)
|
226
|
+
assert_raises ArgumentError do
|
227
|
+
@pen.req_kwargs
|
228
|
+
end
|
229
|
+
assert_raises ArgumentError do
|
230
|
+
@pen.req_kwargs(:pos1, :pos2)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
190
234
|
def test_hook_mimics_public_visibility
|
191
235
|
spy_on(@pen, :public_method)
|
192
236
|
assert @pen.singleton_class.public_method_defined? :public_method
|
data/test/support/pen.rb
CHANGED
@@ -38,6 +38,18 @@ class Pen
|
|
38
38
|
"another"
|
39
39
|
end
|
40
40
|
|
41
|
+
def opt_kwargs(required, opt: nil, opt2: nil)
|
42
|
+
[required, opt: opt, opt2: opt2]
|
43
|
+
end
|
44
|
+
|
45
|
+
def keyrest(**kwargs)
|
46
|
+
kwargs
|
47
|
+
end
|
48
|
+
|
49
|
+
def req_kwargs(req1:, req2:)
|
50
|
+
[req1, req2]
|
51
|
+
end
|
52
|
+
|
41
53
|
protected
|
42
54
|
def protected_method
|
43
55
|
end
|
@@ -65,13 +77,11 @@ class Pen
|
|
65
77
|
end
|
66
78
|
end
|
67
79
|
|
68
|
-
|
69
|
-
|
70
|
-
Pen.define_singleton_method(:meta_method) do
|
71
|
-
another
|
80
|
+
Pen.define_singleton_method(:meta_class_method) do
|
81
|
+
"meta_class_method".freeze
|
72
82
|
end
|
73
83
|
|
74
84
|
Pen.send(:define_method, :meta_method) do
|
75
|
-
|
85
|
+
"meta_method".freeze
|
76
86
|
end
|
77
87
|
|
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,110 +1,126 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Ong
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
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
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: 4.5.0
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
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
|
58
72
|
requirements:
|
59
|
-
- -
|
73
|
+
- - ">="
|
60
74
|
- !ruby/object:Gem::Version
|
61
75
|
version: '0'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
|
-
- -
|
80
|
+
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rspec-expectations
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
|
-
- -
|
87
|
+
- - ">="
|
74
88
|
- !ruby/object:Gem::Version
|
75
89
|
version: '0'
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
|
-
- -
|
94
|
+
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: coveralls
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
|
-
- -
|
101
|
+
- - ">="
|
88
102
|
- !ruby/object:Gem::Version
|
89
103
|
version: '0'
|
90
104
|
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
|
-
- -
|
108
|
+
- - ">="
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '0'
|
97
|
-
description:
|
98
|
-
|
111
|
+
description: Spy is a mocking library that was made for the modern age. It supports
|
112
|
+
only 2.1.0+. Spy by default will raise an error if you attempt to stub a method
|
113
|
+
that doesn't exist or call the stubbed method with the wrong arity.
|
99
114
|
email:
|
100
115
|
- ryanong@gmail.com
|
101
116
|
executables: []
|
102
117
|
extensions: []
|
103
118
|
extra_rdoc_files: []
|
104
119
|
files:
|
105
|
-
- .gitignore
|
106
|
-
- .
|
107
|
-
- .
|
120
|
+
- ".gitignore"
|
121
|
+
- ".tool-versions"
|
122
|
+
- ".travis.yml"
|
123
|
+
- ".yardopts"
|
108
124
|
- CHANGELOG.md
|
109
125
|
- Gemfile
|
110
126
|
- LICENSE.txt
|
@@ -159,22 +175,20 @@ require_paths:
|
|
159
175
|
- lib
|
160
176
|
required_ruby_version: !ruby/object:Gem::Requirement
|
161
177
|
requirements:
|
162
|
-
- -
|
178
|
+
- - ">="
|
163
179
|
- !ruby/object:Gem::Version
|
164
|
-
version: 1.
|
180
|
+
version: 2.1.0
|
165
181
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
166
182
|
requirements:
|
167
|
-
- -
|
183
|
+
- - ">="
|
168
184
|
- !ruby/object:Gem::Version
|
169
185
|
version: '0'
|
170
186
|
requirements: []
|
171
|
-
|
172
|
-
rubygems_version: 2.0.3
|
187
|
+
rubygems_version: 3.1.2
|
173
188
|
signing_key:
|
174
189
|
specification_version: 4
|
175
|
-
summary:
|
176
|
-
|
177
|
-
doesn't exist or call the stubbed method with the wrong arity.
|
190
|
+
summary: A simple modern mocking library that uses the spy pattern and checks method's
|
191
|
+
existence and arity.
|
178
192
|
test_files:
|
179
193
|
- spec/spec_helper.rb
|
180
194
|
- spec/spy/and_call_original_spec.rb
|