much-stub 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 948b3a6fa21e50a2a221b167fe768a5d65c7a61c135622fe6ced882a5e406b03
4
- data.tar.gz: 700d700fab285da4620cb4fbd3b521a58a9ffeaf8d50afdcc96780810091e301
3
+ metadata.gz: 25518cd79915a42ef00d555f2f09db36b19ec52237054c1fb763667ff0a5c4d0
4
+ data.tar.gz: edbd7bd553731a3084806768ad3d956b7f086212b095dfaf63e9eff0ba56cc4e
5
5
  SHA512:
6
- metadata.gz: fecb7b76d76bc9ff338461c7ec6a48ac3bf1833bd77f4f248c9d4a145fa0b0177b3ce9d99d01add632266d7f9c5731441f0ad553f14775e7cf704aaffc80099a
7
- data.tar.gz: 55308114a2f7aac2294ba44aac2adf84152cc2213a40a9ff0118b3fe2e8d43738cbc617fb19855c63515e915bc46754fc915d86b568d7a9c97356fb619420156
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
- iterator_method_call_args = nil
121
- iterator_method_call_block = nil
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
- iterator_method_call_args = args
124
- iterator_method_call_block = block
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
- iterator_method_call_args
147
+ iterator_method_called_with.args
129
148
  # => [[1, 2, 3]]
130
- iterator_method_call_block
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:
@@ -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
- msg = "arity mismatch on `#{@method_name}`: " \
80
- "expected #{number_of_args(@method.arity)}, " \
81
- "called with #{args.size}"
82
- raise StubArityError, msg, orig_caller.map(&:to_s)
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
- msg = "arity mismatch on `#{@method_name}`: " \
94
- "expected #{number_of_args(@method.arity)}, " \
95
- "stubbed with #{args.size}"
96
- raise StubArityError, msg, orig_caller.map(&:to_s)
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) do
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
- end
155
- end
156
-
157
- def arity_matches?(args)
158
- return true if @method.arity == args.size # mandatory args
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 = Class.new(StubError)
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
@@ -1,3 +1,3 @@
1
1
  module MuchStub
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -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.add_development_dependency("assert", ["~> 2.18.0"])
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
- MuchStub::Stub.new(@myobj, :mymeth){ "mymeth" }
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
- assert_equal "3,4,5", @myobj.myargs(3,4,5)
233
- stub.with(3,4,5){ "three-four-five" }
234
- assert_equal "three-four-five", @myobj.myargs(3,4,5)
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
- assert_equal "3,4,5", @myobj.myvalargs(3,4,5)
242
- stub.with(3,4,5){ "three-four-five" }
243
- assert_equal "three-four-five", @myobj.myvalargs(3,4,5)
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 on asserts main module" do
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.2
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-01-13 00:00:00.000000000 Z
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.0
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.0
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: '0'
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
- rubyforge_project:
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