much-stub 0.1.2 → 0.1.3
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 +4 -4
- data/README.md +72 -12
- data/lib/much-stub.rb +80 -27
- data/lib/much-stub/call.rb +15 -0
- data/lib/much-stub/call_spy.rb +91 -0
- data/lib/much-stub/version.rb +1 -1
- data/much-stub.gemspec +3 -1
- data/test/unit/call_spy_tests.rb +96 -0
- data/test/unit/call_tests.rb +68 -0
- data/test/unit/much-stub_tests.rb +69 -13
- metadata +13 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 25518cd79915a42ef00d555f2f09db36b19ec52237054c1fb763667ff0a5c4d0
|
4
|
+
data.tar.gz: edbd7bd553731a3084806768ad3d956b7f086212b095dfaf63e9eff0ba56cc4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb69a558eb21bbd717bb9164a5142c318697ea512e0234dd110c0127eaa9eef68a25abd13c2d9c4136dc9474712312a85fb5af8a30fc7dcaf8c7b1cc6d8606c4
|
7
|
+
data.tar.gz: 390126be543ddf6c36fcf7dd3c0491c5530ba8535b049b91edf9de6a3461895f5b4f673d2ef0b5b920af30880e71ea705f1043648edef75ede03b9c1af74b311
|
data/README.md
CHANGED
@@ -110,24 +110,43 @@ my_object = my_class.new
|
|
110
110
|
|
111
111
|
basic_method_called_with = nil
|
112
112
|
MuchStub.(my_object, :basic_method) { |*args|
|
113
|
-
basic_method_called_with = args
|
113
|
+
basic_method_called_with = MuchStub::Call.new(*args)
|
114
|
+
}
|
115
|
+
# OR
|
116
|
+
MuchStub.(my_object, :basic_method).on_call { |call|
|
117
|
+
basic_method_called_with = call
|
114
118
|
}
|
115
119
|
|
116
120
|
my_object.basic_method(123)
|
117
|
-
basic_method_called_with
|
121
|
+
basic_method_called_with.args
|
118
122
|
# => [123]
|
119
123
|
|
120
|
-
|
121
|
-
|
124
|
+
basic_method_called_with = nil
|
125
|
+
MuchStub.(my_object, :basic_method).with(4, 5, 6) { |*args|
|
126
|
+
basic_method_called_with = MuchStub::Call.new(*args)
|
127
|
+
}
|
128
|
+
# OR
|
129
|
+
MuchStub.(my_object, :basic_method).with(4, 5, 6).on_call { |call|
|
130
|
+
basic_method_called_with = call
|
131
|
+
}
|
132
|
+
|
133
|
+
my_object.basic_method(4, 5, 6)
|
134
|
+
basic_method_called_with.args
|
135
|
+
# => [4,5,6]
|
136
|
+
|
137
|
+
iterator_method_called_with = nil
|
122
138
|
MuchStub.(my_object, :iterator_method) { |*args, &block|
|
123
|
-
|
124
|
-
|
139
|
+
iterator_method_called_with = MuchStub::Call.new(*args)
|
140
|
+
}
|
141
|
+
# OR
|
142
|
+
MuchStub.(my_object, :iterator_method).on_call { |call|
|
143
|
+
iterator_method_called_with = call
|
125
144
|
}
|
126
145
|
|
127
146
|
my_object.iterator_method([1, 2, 3], &:to_s)
|
128
|
-
|
147
|
+
iterator_method_called_with.args
|
129
148
|
# => [[1, 2, 3]]
|
130
|
-
|
149
|
+
iterator_method_called_with.block
|
131
150
|
# => #<Proc:0x00007fb083a6feb0(&:to_s)>
|
132
151
|
|
133
152
|
# Count method calls for spying.
|
@@ -145,13 +164,17 @@ basic_method_call_count
|
|
145
164
|
|
146
165
|
basic_method_calls = []
|
147
166
|
MuchStub.(my_object, :basic_method) { |*args|
|
148
|
-
basic_method_calls << args
|
167
|
+
basic_method_calls << MuchStub::Call.new(*args)
|
168
|
+
}
|
169
|
+
# OR
|
170
|
+
MuchStub.(my_object, :basic_method).on_call { |call|
|
171
|
+
basic_method_calls << call
|
149
172
|
}
|
150
173
|
|
151
174
|
my_object.basic_method(123)
|
152
175
|
basic_method_calls.size
|
153
176
|
# => 1
|
154
|
-
basic_method_calls.first
|
177
|
+
basic_method_calls.first.args
|
155
178
|
# => [123]
|
156
179
|
```
|
157
180
|
|
@@ -218,12 +241,16 @@ basic_method_called_with
|
|
218
241
|
|
219
242
|
basic_method_called_with = nil
|
220
243
|
MuchStub.tap(my_object, :basic_method) { |value, *args|
|
221
|
-
basic_method_called_with = args
|
244
|
+
basic_method_called_with = MuchStub::Call.new(*args)
|
245
|
+
}
|
246
|
+
# OR
|
247
|
+
MuchStub.tap_on_call(my_object, :basic_method) { |value, call|
|
248
|
+
basic_method_called_with = call
|
222
249
|
}
|
223
250
|
|
224
251
|
my_object.basic_method(123)
|
225
252
|
# => "123"
|
226
|
-
basic_method_called_with
|
253
|
+
basic_method_called_with.args
|
227
254
|
# => [123]
|
228
255
|
```
|
229
256
|
|
@@ -266,6 +293,39 @@ thing.value
|
|
266
293
|
# => 456
|
267
294
|
```
|
268
295
|
|
296
|
+
### `MuchStub.spy`
|
297
|
+
|
298
|
+
Use the `.spy` method to spy on method calls. This is especially helpful for spying on _chained_ method calls.
|
299
|
+
|
300
|
+
```ruby
|
301
|
+
# Given this object/API
|
302
|
+
|
303
|
+
myclass = Class.new do
|
304
|
+
def one; self; end
|
305
|
+
def two(val); self; end
|
306
|
+
def three; self; end
|
307
|
+
def ready?; false; end
|
308
|
+
end
|
309
|
+
myobj = myclass.new
|
310
|
+
|
311
|
+
spy =
|
312
|
+
MuchStub.spy(myobj :one, :two, :three, ready?: true)
|
313
|
+
|
314
|
+
assert_equal spy, myobj.one
|
315
|
+
assert_equal spy, myobj.two("a")
|
316
|
+
assert_equal spy, myobj.three
|
317
|
+
|
318
|
+
assert_true myobj.one.two("b").three.ready?
|
319
|
+
|
320
|
+
assert_kind_of MuchStub::CallSpy, spy
|
321
|
+
assert_equal 2, spy.one_call_count
|
322
|
+
assert_equal 2, spy.two_call_count
|
323
|
+
assert_equal 2, spy.three_call_count
|
324
|
+
assert_equal 1, spy.ready_predicate_call_count
|
325
|
+
assert_equal ["b"], spy.two_last_called_with.args
|
326
|
+
assert_true spy.ready_predicate_called?
|
327
|
+
```
|
328
|
+
|
269
329
|
## Installation
|
270
330
|
|
271
331
|
Add this line to your application's Gemfile:
|
data/lib/much-stub.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require "much-stub/version"
|
2
2
|
|
3
|
+
require "much-stub/call"
|
4
|
+
require "much-stub/call_spy"
|
5
|
+
|
3
6
|
module MuchStub
|
4
7
|
def self.stubs
|
5
8
|
@stubs ||= {}
|
@@ -9,6 +12,12 @@ module MuchStub
|
|
9
12
|
MuchStub::Stub.key(obj, meth)
|
10
13
|
end
|
11
14
|
|
15
|
+
def self.arity_matches?(method, args)
|
16
|
+
return true if method.arity == args.size # mandatory args
|
17
|
+
return true if method.arity < 0 && args.size >= (method.arity+1).abs # variable args
|
18
|
+
return false
|
19
|
+
end
|
20
|
+
|
12
21
|
def self.call(*args, &block)
|
13
22
|
self.stub(*args, &block)
|
14
23
|
end
|
@@ -44,6 +53,22 @@ module MuchStub
|
|
44
53
|
}
|
45
54
|
end
|
46
55
|
|
56
|
+
def self.tap_on_call(obj, meth, &on_call_block)
|
57
|
+
self.tap(obj, meth) { |value, *args, &block|
|
58
|
+
on_call_block.call(value, MuchStub::Call.new(*args, &block)) if on_call_block
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.spy(obj, *meths, **return_values)
|
63
|
+
MuchStub::CallSpy.new(**return_values).tap do |spy|
|
64
|
+
meths.each do |meth|
|
65
|
+
self.stub(obj, meth) { |*args, &block|
|
66
|
+
spy.public_send(meth, *args, &block)
|
67
|
+
}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
47
72
|
class Stub
|
48
73
|
def self.key(object, method_name)
|
49
74
|
"--#{object.object_id}--#{method_name}--"
|
@@ -75,11 +100,13 @@ module MuchStub
|
|
75
100
|
|
76
101
|
def call(args, orig_caller = nil, &block)
|
77
102
|
orig_caller ||= caller_locations
|
78
|
-
unless arity_matches?(args)
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
103
|
+
unless MuchStub.arity_matches?(@method, args)
|
104
|
+
raise(
|
105
|
+
StubArityError.new(
|
106
|
+
@method,
|
107
|
+
args,
|
108
|
+
method_name: @method_name,
|
109
|
+
backtrace: orig_caller))
|
83
110
|
end
|
84
111
|
lookup(args, orig_caller).call(*args, &block)
|
85
112
|
rescue NotStubbedError
|
@@ -89,13 +116,29 @@ module MuchStub
|
|
89
116
|
|
90
117
|
def with(*args, &block)
|
91
118
|
orig_caller = caller_locations
|
92
|
-
unless arity_matches?(args)
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
119
|
+
unless MuchStub.arity_matches?(@method, args)
|
120
|
+
raise(
|
121
|
+
StubArityError.new(
|
122
|
+
@method,
|
123
|
+
args,
|
124
|
+
method_name: @method_name,
|
125
|
+
backtrace: orig_caller))
|
97
126
|
end
|
98
127
|
@lookup[args] = block
|
128
|
+
self
|
129
|
+
end
|
130
|
+
|
131
|
+
def on_call(&on_call_block)
|
132
|
+
stub_block =
|
133
|
+
->(*args, &block) {
|
134
|
+
on_call_block.call(MuchStub::Call.new(*args, &block)) if on_call_block
|
135
|
+
}
|
136
|
+
if @lookup.empty?
|
137
|
+
@do = stub_block
|
138
|
+
elsif @lookup.has_value?(nil)
|
139
|
+
@lookup.transform_values!{ |value| value.nil? ? stub_block : value }
|
140
|
+
end
|
141
|
+
self
|
99
142
|
end
|
100
143
|
|
101
144
|
def teardown
|
@@ -143,7 +186,7 @@ module MuchStub
|
|
143
186
|
end
|
144
187
|
|
145
188
|
def lookup(args, orig_caller)
|
146
|
-
@lookup.fetch(args)
|
189
|
+
@lookup.fetch(args) {
|
147
190
|
self.do || begin
|
148
191
|
msg = "#{inspect_call(args)} not stubbed."
|
149
192
|
inspect_lookup_stubs.tap do |stubs|
|
@@ -151,13 +194,11 @@ module MuchStub
|
|
151
194
|
end
|
152
195
|
raise NotStubbedError, msg, orig_caller.map(&:to_s)
|
153
196
|
end
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
return true if @method.arity < 0 && args.size >= (@method.arity+1).abs # variable args
|
160
|
-
return false
|
197
|
+
} ||
|
198
|
+
raise(
|
199
|
+
StubError,
|
200
|
+
"#{inspect_call(args)} stubbed with no block.",
|
201
|
+
orig_caller.map(&:to_s))
|
161
202
|
end
|
162
203
|
|
163
204
|
def inspect_lookup_stubs
|
@@ -167,19 +208,31 @@ module MuchStub
|
|
167
208
|
def inspect_call(args)
|
168
209
|
"`#{@method_name}(#{args.map(&:inspect).join(",")})`"
|
169
210
|
end
|
170
|
-
|
171
|
-
def number_of_args(arity)
|
172
|
-
if arity < 0
|
173
|
-
"at least #{(arity + 1).abs}"
|
174
|
-
else
|
175
|
-
arity
|
176
|
-
end
|
177
|
-
end
|
178
211
|
end
|
179
212
|
|
180
213
|
StubError = Class.new(ArgumentError)
|
181
214
|
NotStubbedError = Class.new(StubError)
|
182
|
-
StubArityError =
|
215
|
+
StubArityError =
|
216
|
+
Class.new(StubError) do
|
217
|
+
def initialize(method, args, method_name:, backtrace:)
|
218
|
+
msg = "arity mismatch on `#{method_name}`: " \
|
219
|
+
"expected #{number_of_args(method.arity)}, " \
|
220
|
+
"called with #{args.size}"
|
221
|
+
|
222
|
+
super(msg)
|
223
|
+
set_backtrace(Array(backtrace).map(&:to_s))
|
224
|
+
end
|
225
|
+
|
226
|
+
private
|
227
|
+
|
228
|
+
def number_of_args(arity)
|
229
|
+
if arity < 0
|
230
|
+
"at least #{(arity + 1).abs}"
|
231
|
+
else
|
232
|
+
arity
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
183
236
|
|
184
237
|
NullStub = Class.new do
|
185
238
|
def teardown; end # no-op
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module MuchStub
|
2
|
+
class Call
|
3
|
+
attr_reader :pargs, :kargs, :block
|
4
|
+
|
5
|
+
def initialize(*pargs, **kargs, &block)
|
6
|
+
@pargs = pargs.empty? ? nil : pargs
|
7
|
+
@kargs = kargs.empty? ? nil : kargs
|
8
|
+
@block = block
|
9
|
+
end
|
10
|
+
|
11
|
+
def args
|
12
|
+
@args ||= [*pargs, kargs].compact
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require "much-stub/call"
|
2
|
+
|
3
|
+
module MuchStub
|
4
|
+
class CallSpy
|
5
|
+
METHOD_NAME_REPLACEMENTS = {
|
6
|
+
"!" => "_bang",
|
7
|
+
"?" => "_predicate"
|
8
|
+
}.freeze
|
9
|
+
|
10
|
+
def initialize(**return_values)
|
11
|
+
@call_spy_return_values = return_values.transform_keys{ |key| key.to_s }
|
12
|
+
|
13
|
+
@call_spy_method_calls = Hash.new { |hash, key| hash[key] = [] }
|
14
|
+
@call_spy_method_return_values =
|
15
|
+
Hash.new { |hash, key| hash[key] = call_spy_return_value_proc(key) }
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def call_spy_method_return_value(method_name, much_stub_call)
|
21
|
+
@call_spy_method_return_values[method_name.to_s].call(much_stub_call)
|
22
|
+
end
|
23
|
+
|
24
|
+
def call_spy_return_value_proc(method_name)
|
25
|
+
value = @call_spy_return_values[method_name]
|
26
|
+
return value if value.respond_to?(:call)
|
27
|
+
|
28
|
+
->(*) { value.nil? ? self : value }
|
29
|
+
end
|
30
|
+
|
31
|
+
def call_spy_normalize_method_name(name)
|
32
|
+
METHOD_NAME_REPLACEMENTS.reduce(name.to_s) { |acc, (source, replacement)|
|
33
|
+
acc.gsub(source, replacement)
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def call_spy_define_spied_method(name)
|
38
|
+
method_name = call_spy_normalize_method_name(name)
|
39
|
+
self.define_singleton_method(name) do |*args, &block|
|
40
|
+
call = MuchStub::Call.new(*args, &block)
|
41
|
+
@call_spy_method_calls[method_name] << call
|
42
|
+
call_spy_method_return_value(name, call)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def call_spy_define_query_method(query_method_match)
|
47
|
+
spied_method_name = query_method_match[1]
|
48
|
+
query_method_suffix = query_method_match[2]
|
49
|
+
method_name = call_spy_normalize_method_name(spied_method_name)
|
50
|
+
self.define_singleton_method("#{method_name}#{query_method_suffix}") do
|
51
|
+
yield(method_name) if block_given?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def method_missing(name, *args, &block)
|
56
|
+
if (match = name.match(/(\w+)(_calls)\z/))
|
57
|
+
call_spy_define_query_method(match) do |method_name|
|
58
|
+
@call_spy_method_calls[method_name]
|
59
|
+
end
|
60
|
+
self.send(name, *args, &block)
|
61
|
+
elsif (match = name.match(/(\w+)(_last_called_with)\z/))
|
62
|
+
call_spy_define_query_method(match) do |method_name|
|
63
|
+
self.send("#{method_name}_calls").last
|
64
|
+
end
|
65
|
+
self.send(name, *args, &block)
|
66
|
+
elsif (match = name.match(/(\w+)(_called_with)\z/))
|
67
|
+
call_spy_define_query_method(match) do |method_name|
|
68
|
+
self.send("#{method_name}_last_called_with")
|
69
|
+
end
|
70
|
+
self.send(name, *args, &block)
|
71
|
+
elsif (match = name.match(/(\w+)(_call_count)\z/))
|
72
|
+
call_spy_define_query_method(match) do |method_name|
|
73
|
+
self.send("#{method_name}_calls").size
|
74
|
+
end
|
75
|
+
self.send(name, *args, &block)
|
76
|
+
elsif (match = name.match(/(\w+)(_called\?)\z/))
|
77
|
+
call_spy_define_query_method(match) do |method_name|
|
78
|
+
self.send("#{method_name}_call_count") > 0
|
79
|
+
end
|
80
|
+
self.send(name, *args, &block)
|
81
|
+
else
|
82
|
+
call_spy_define_spied_method(name)
|
83
|
+
self.send(name, *args, &block)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def respond_to_missing?(*args)
|
88
|
+
super
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/much-stub/version.rb
CHANGED
data/much-stub.gemspec
CHANGED
@@ -18,6 +18,8 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
|
21
|
-
gem.
|
21
|
+
gem.required_ruby_version = "~> 2.5"
|
22
|
+
|
23
|
+
gem.add_development_dependency("assert", ["~> 2.18.1"])
|
22
24
|
|
23
25
|
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require "assert"
|
2
|
+
require "much-stub/call_spy"
|
3
|
+
|
4
|
+
require "test/support/factory"
|
5
|
+
|
6
|
+
class MuchStub::CallSpy
|
7
|
+
class UnitTests < Assert::Context
|
8
|
+
desc "MuchStub::CallSpy"
|
9
|
+
setup do
|
10
|
+
@unit_class = MuchStub::CallSpy
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class InitTests < UnitTests
|
15
|
+
desc "when init"
|
16
|
+
before do
|
17
|
+
@spy = @unit_class.new
|
18
|
+
end
|
19
|
+
subject{ @spy }
|
20
|
+
|
21
|
+
should "spy on method calls and return itself" do
|
22
|
+
assert_false subject.respond_to?(:get)
|
23
|
+
|
24
|
+
assert_equal [], subject.get_calls
|
25
|
+
assert_nil subject.get_last_called_with
|
26
|
+
assert_nil subject.get_called_with
|
27
|
+
assert_equal 0, subject.get_call_count
|
28
|
+
assert_false subject.get_called?
|
29
|
+
|
30
|
+
assert_same subject, subject.get
|
31
|
+
|
32
|
+
assert_true subject.respond_to?(:get)
|
33
|
+
|
34
|
+
assert_kind_of Array, subject.get_calls
|
35
|
+
assert_kind_of MuchStub::Call, subject.get_last_called_with
|
36
|
+
assert_equal [], subject.get_last_called_with.args
|
37
|
+
assert_equal subject.get_last_called_with, subject.get_called_with
|
38
|
+
assert_equal 1, subject.get_call_count
|
39
|
+
assert_true subject.get_called?
|
40
|
+
|
41
|
+
assert_same subject, subject.set!("value1")
|
42
|
+
assert_same subject, subject.set!("value2")
|
43
|
+
|
44
|
+
assert_kind_of Array, subject.set_bang_calls
|
45
|
+
assert_kind_of MuchStub::Call, subject.set_bang_last_called_with
|
46
|
+
assert_equal ["value2"], subject.set_bang_last_called_with.args
|
47
|
+
assert_equal 2, subject.set_bang_call_count
|
48
|
+
assert_true subject.set_bang_called?
|
49
|
+
end
|
50
|
+
|
51
|
+
should "normalize method names in call query methods" do
|
52
|
+
assert_same subject, subject.set!("value1")
|
53
|
+
assert_kind_of Array, subject.set_bang_calls
|
54
|
+
assert_kind_of MuchStub::Call, subject.set_bang_last_called_with
|
55
|
+
assert_equal ["value1"], subject.set_bang_last_called_with.args
|
56
|
+
assert_equal ["value1"], subject.set_bang_called_with.args
|
57
|
+
assert_equal 1, subject.set_bang_call_count
|
58
|
+
assert_true subject.set_bang_called?
|
59
|
+
|
60
|
+
assert_same subject, subject.any?
|
61
|
+
assert_kind_of Array, subject.any_predicate_calls
|
62
|
+
assert_kind_of MuchStub::Call, subject.any_predicate_last_called_with
|
63
|
+
assert_kind_of MuchStub::Call, subject.any_predicate_called_with
|
64
|
+
assert_equal 1, subject.any_predicate_call_count
|
65
|
+
assert_true subject.any_predicate_called?
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class InitWithReturnValuesTests < UnitTests
|
70
|
+
desc "when init with return values"
|
71
|
+
setup do
|
72
|
+
@spy = @unit_class.new(any?: false)
|
73
|
+
end
|
74
|
+
subject{ @spy }
|
75
|
+
|
76
|
+
should "return the given values instead of itself if that method is called" do
|
77
|
+
assert_false subject.get.set!("value1").any?
|
78
|
+
assert_true subject.get_called?
|
79
|
+
assert_equal ["value1"], subject.set_bang_called_with.args
|
80
|
+
assert_true subject.any_predicate_called?
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class InitWithReturnValueProcsTests < UnitTests
|
85
|
+
desc "when init with return value procs"
|
86
|
+
setup do
|
87
|
+
@result = Factory.boolean
|
88
|
+
@spy = @unit_class.new(any?: ->(call) { @result })
|
89
|
+
end
|
90
|
+
subject{ @spy }
|
91
|
+
|
92
|
+
should "return the value of calling the procs instead of itself" do
|
93
|
+
assert_equal @result, subject.get.set!("value1").any?
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "assert"
|
2
|
+
require "much-stub/call"
|
3
|
+
|
4
|
+
require "test/support/factory"
|
5
|
+
|
6
|
+
class MuchStub::Call
|
7
|
+
class UnitTests < Assert::Context
|
8
|
+
desc "MuchStub::Call"
|
9
|
+
setup do
|
10
|
+
@unit_class = MuchStub::Call
|
11
|
+
|
12
|
+
@pargs = [Factory.string, Factory.integer]
|
13
|
+
@kargs = {
|
14
|
+
one: 1,
|
15
|
+
two: 2
|
16
|
+
}
|
17
|
+
@block = -> {}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class InitWithNoArgsTests < UnitTests
|
22
|
+
desc "when init with no args"
|
23
|
+
subject{ @unit_class.new }
|
24
|
+
|
25
|
+
should "know its attrs" do
|
26
|
+
assert_nil subject.pargs
|
27
|
+
assert_nil subject.kargs
|
28
|
+
assert_equal [], subject.args
|
29
|
+
assert_nil subject.block
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class InitWithOnlyPositionalArgsTests < UnitTests
|
34
|
+
desc "when init with only positional args"
|
35
|
+
subject{ @unit_class.new(*@pargs) }
|
36
|
+
|
37
|
+
should "know its attrs" do
|
38
|
+
assert_equal @pargs, subject.pargs
|
39
|
+
assert_nil subject.kargs
|
40
|
+
assert_equal [*@pargs], subject.args
|
41
|
+
assert_nil subject.block
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class InitWithOnlyKeywordArgsTests < UnitTests
|
46
|
+
desc "when init with only keyword args"
|
47
|
+
subject{ @unit_class.new(**@kargs) }
|
48
|
+
|
49
|
+
should "know its attrs" do
|
50
|
+
assert_nil subject.pargs
|
51
|
+
assert_equal @kargs, subject.kargs
|
52
|
+
assert_equal [@kargs], subject.args
|
53
|
+
assert_nil subject.block
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class InitWithBothPositionalAndKeywordArgsTests < UnitTests
|
58
|
+
desc "when init with only keyword args"
|
59
|
+
subject{ @unit_class.new(*@pargs, **@kargs, &@block) }
|
60
|
+
|
61
|
+
should "know its attrs" do
|
62
|
+
assert_equal @pargs, subject.pargs
|
63
|
+
assert_equal @kargs, subject.kargs
|
64
|
+
assert_equal [*@pargs, @kargs], subject.args
|
65
|
+
assert_equal @block, subject.block
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -86,6 +86,48 @@ module MuchStub
|
|
86
86
|
assert_equal @orig_value, @myobj.mymeth
|
87
87
|
assert_equal [], my_meth_called_with
|
88
88
|
end
|
89
|
+
|
90
|
+
should "be able to add a stub tap with an on_call block" do
|
91
|
+
my_meth_called_with = nil
|
92
|
+
MuchStub.tap_on_call(@myobj, :mymeth){ |value, call|
|
93
|
+
my_meth_called_with = call
|
94
|
+
}
|
95
|
+
|
96
|
+
assert_equal @orig_value, @myobj.mymeth
|
97
|
+
assert_equal [], my_meth_called_with.args
|
98
|
+
end
|
99
|
+
|
100
|
+
should "be able to add a stubbed spy" do
|
101
|
+
myclass = Class.new do
|
102
|
+
def one; self; end
|
103
|
+
def two(val); self; end
|
104
|
+
def three; self; end
|
105
|
+
def ready?; false; end
|
106
|
+
end
|
107
|
+
myobj = myclass.new
|
108
|
+
|
109
|
+
spy =
|
110
|
+
MuchStub.spy(
|
111
|
+
myobj,
|
112
|
+
:one,
|
113
|
+
:two,
|
114
|
+
:three,
|
115
|
+
ready?: true)
|
116
|
+
|
117
|
+
assert_equal spy, myobj.one
|
118
|
+
assert_equal spy, myobj.two("a")
|
119
|
+
assert_equal spy, myobj.three
|
120
|
+
|
121
|
+
assert_true myobj.one.two("b").three.ready?
|
122
|
+
|
123
|
+
assert_kind_of MuchStub::CallSpy, spy
|
124
|
+
assert_equal 2, spy.one_call_count
|
125
|
+
assert_equal 2, spy.two_call_count
|
126
|
+
assert_equal 2, spy.three_call_count
|
127
|
+
assert_equal 1, spy.ready_predicate_call_count
|
128
|
+
assert_equal ["b"], spy.two_last_called_with.args
|
129
|
+
assert_true spy.ready_predicate_called?
|
130
|
+
end
|
89
131
|
end
|
90
132
|
|
91
133
|
class StubTests < UnitTests
|
@@ -134,21 +176,26 @@ module MuchStub
|
|
134
176
|
@myobj.mymeth
|
135
177
|
end
|
136
178
|
|
179
|
+
MuchStub::Stub.new(@myobj, :mymeth){ "mymeth" }
|
137
180
|
assert_nothing_raised do
|
138
|
-
|
181
|
+
@myobj.mymeth
|
139
182
|
end
|
140
183
|
end
|
141
184
|
|
185
|
+
should "complain when called if no lookup block was given" do
|
186
|
+
MuchStub::Stub.new(@myobj, :myval).with(1)
|
187
|
+
|
188
|
+
err = assert_raises(MuchStub::StubError){ @myobj.myval(1) }
|
189
|
+
assert_includes "stubbed with no block.", err.message
|
190
|
+
assert_includes "test/unit/much-stub_tests.rb", err.backtrace.first
|
191
|
+
end
|
192
|
+
|
142
193
|
should "complain if stubbing a method that the object doesn't respond to" do
|
143
194
|
err = assert_raises(MuchStub::StubError){ MuchStub::Stub.new(@myobj, :some_other_meth) }
|
144
195
|
assert_includes "does not respond to", err.message
|
145
196
|
assert_includes "test/unit/much-stub_tests.rb", err.backtrace.first
|
146
197
|
end
|
147
198
|
|
148
|
-
should "complain if stubbed and called with no `do` proc given" do
|
149
|
-
assert_raises(MuchStub::NotStubbedError){ @myobj.mymeth }
|
150
|
-
end
|
151
|
-
|
152
199
|
should "complain if stubbed and called with mismatched arity" do
|
153
200
|
MuchStub::Stub.new(@myobj, :myval){ "myval" }
|
154
201
|
err = assert_raises(MuchStub::StubArityError){ @myobj.myval }
|
@@ -227,20 +274,29 @@ module MuchStub
|
|
227
274
|
|
228
275
|
should "stub methods with variable args" do
|
229
276
|
assert_equal [1,2], @myobj.myargs(1,2)
|
277
|
+
|
230
278
|
stub = MuchStub::Stub.new(@myobj, :myargs){ |*args| args.join(",") }
|
231
|
-
assert_equal "1,2", @myobj.myargs(1,2)
|
232
|
-
|
233
|
-
|
234
|
-
|
279
|
+
assert_equal "1,2,3", @myobj.myargs(1,2,3)
|
280
|
+
stub.with(3,4,5){ |*args| args.join(":") }
|
281
|
+
assert_equal "3:4:5", @myobj.myargs(3,4,5)
|
282
|
+
|
283
|
+
stub = MuchStub::Stub.new(@myobj, :myargs).on_call{ |call| call.args.join(",") }
|
284
|
+
assert_equal "1,2,3", @myobj.myargs(1,2,3)
|
285
|
+
stub.with(3,4,5).on_call{ |call| call.args.join(":") }
|
286
|
+
assert_equal "3:4:5", @myobj.myargs(3,4,5)
|
235
287
|
end
|
236
288
|
|
237
289
|
should "stub methods with required args and variable args" do
|
238
290
|
assert_equal [1,2, [3]], @myobj.myvalargs(1,2,3)
|
239
291
|
stub = MuchStub::Stub.new(@myobj, :myvalargs){ |*args| args.join(",") }
|
240
292
|
assert_equal "1,2,3", @myobj.myvalargs(1,2,3)
|
241
|
-
|
242
|
-
|
243
|
-
|
293
|
+
stub.with(3,4,5){ |*args| args.join(":") }
|
294
|
+
assert_equal "3:4:5", @myobj.myvalargs(3,4,5)
|
295
|
+
|
296
|
+
stub = MuchStub::Stub.new(@myobj, :myvalargs).on_call{ |call| call.args.join(",") }
|
297
|
+
assert_equal "1,2,3", @myobj.myvalargs(1,2,3)
|
298
|
+
stub.with(3,4,5).on_call{ |call| call.args.join(":") }
|
299
|
+
assert_equal "3:4:5", @myobj.myvalargs(3,4,5)
|
244
300
|
end
|
245
301
|
|
246
302
|
should "stub methods that yield blocks" do
|
@@ -325,7 +381,7 @@ module MuchStub
|
|
325
381
|
assert_equal true, blkcalled
|
326
382
|
end
|
327
383
|
|
328
|
-
should "store and remove itself
|
384
|
+
should "store and remove itself" do
|
329
385
|
assert_equal subject, MuchStub.instance_variable_get(subject.ivar_name)
|
330
386
|
subject.teardown
|
331
387
|
assert_nil MuchStub.instance_variable_get(subject.ivar_name)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: much-stub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kelly Redding
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-07-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: assert
|
@@ -17,14 +17,14 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 2.18.
|
20
|
+
version: 2.18.1
|
21
21
|
type: :development
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 2.18.
|
27
|
+
version: 2.18.1
|
28
28
|
description: Stubbing API for replacing method calls on objects in test runs.
|
29
29
|
email:
|
30
30
|
- kelly@kellyredding.com
|
@@ -38,12 +38,16 @@ files:
|
|
38
38
|
- LICENSE
|
39
39
|
- README.md
|
40
40
|
- lib/much-stub.rb
|
41
|
+
- lib/much-stub/call.rb
|
42
|
+
- lib/much-stub/call_spy.rb
|
41
43
|
- lib/much-stub/version.rb
|
42
44
|
- log/.gitkeep
|
43
45
|
- much-stub.gemspec
|
44
46
|
- test/helper.rb
|
45
47
|
- test/support/factory.rb
|
46
48
|
- test/system/much-stub_tests.rb
|
49
|
+
- test/unit/call_spy_tests.rb
|
50
|
+
- test/unit/call_tests.rb
|
47
51
|
- test/unit/much-stub_tests.rb
|
48
52
|
- tmp/.gitkeep
|
49
53
|
homepage: https://github.com/redding/much-stub
|
@@ -56,17 +60,16 @@ require_paths:
|
|
56
60
|
- lib
|
57
61
|
required_ruby_version: !ruby/object:Gem::Requirement
|
58
62
|
requirements:
|
59
|
-
- - "
|
63
|
+
- - "~>"
|
60
64
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
65
|
+
version: '2.5'
|
62
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
67
|
requirements:
|
64
68
|
- - ">="
|
65
69
|
- !ruby/object:Gem::Version
|
66
70
|
version: '0'
|
67
71
|
requirements: []
|
68
|
-
|
69
|
-
rubygems_version: 2.7.6.2
|
72
|
+
rubygems_version: 3.1.2
|
70
73
|
signing_key:
|
71
74
|
specification_version: 4
|
72
75
|
summary: Stubbing API for replacing method calls on objects in test runs.
|
@@ -74,4 +77,6 @@ test_files:
|
|
74
77
|
- test/helper.rb
|
75
78
|
- test/support/factory.rb
|
76
79
|
- test/system/much-stub_tests.rb
|
80
|
+
- test/unit/call_spy_tests.rb
|
81
|
+
- test/unit/call_tests.rb
|
77
82
|
- test/unit/much-stub_tests.rb
|