much-stub 0.1.1 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 405abaae599baf274c0eea900413f3c534c3acf1a19b4a83a356f5c61640025b
4
- data.tar.gz: e68b22427ea8c78b87023576611a94c750a9d4ed75989cc72b7cdc96a56ebf2d
3
+ metadata.gz: 948b3a6fa21e50a2a221b167fe768a5d65c7a61c135622fe6ced882a5e406b03
4
+ data.tar.gz: 700d700fab285da4620cb4fbd3b521a58a9ffeaf8d50afdcc96780810091e301
5
5
  SHA512:
6
- metadata.gz: d1cafda498eceb26c4d41a4b4867c0376dc36d34149454350e3ac4ef8a04623ee747a6d28639e417cac93eeb1f4950c1fda696153be860c61e9fef8be8f36a3e
7
- data.tar.gz: 416559df2f95b8faa18fac713e924e5af8ac128b2b385a91623f32939396488f9f2a0ecef01649c3099b076e385270cbae2f5f79a84e0e26d54c689c193e7e7e
6
+ metadata.gz: fecb7b76d76bc9ff338461c7ec6a48ac3bf1833bd77f4f248c9d4a145fa0b0177b3ce9d99d01add632266d7f9c5731441f0ad553f14775e7cf704aaffc80099a
7
+ data.tar.gz: 55308114a2f7aac2294ba44aac2adf84152cc2213a40a9ff0118b3fe2e8d43738cbc617fb19855c63515e915bc46754fc915d86b568d7a9c97356fb619420156
data/Gemfile CHANGED
@@ -2,4 +2,4 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'pry', "~> 0.9.0"
5
+ gem "pry", "~> 0.12.2"
data/README.md CHANGED
@@ -16,69 +16,253 @@ Note: this was originally implemented in and extracted from [Assert](https://git
16
16
  ```ruby
17
17
  # Given this object/API
18
18
 
19
- myclass = Class.new do
20
- def mymeth; 'meth'; end
21
- def myval(val); val; end
19
+ my_class = Class.new do
20
+ def my_method
21
+ "my-method"
22
+ end
23
+
24
+ def my_value(value)
25
+ value
26
+ end
22
27
  end
23
- myobj = myclass.new
28
+ my_object = my_class.new
24
29
 
25
- myobj.mymeth
26
- # => 'meth'
27
- myobj.myval(123)
30
+ my_object.my_method
31
+ # => "my-method"
32
+ my_object.my_value(123)
28
33
  # => 123
29
- myobj.myval(456)
34
+ my_object.my_value(456)
30
35
  # => 456
31
36
 
32
- # Create a new stub for the :mymeth method
37
+ # Create a new stub for the :my_method method
33
38
 
34
- MuchStub.(myobj, :mymeth)
35
- myobj.mymeth
36
- # => StubError: `mymeth` not stubbed.
37
- MuchStub.(myobj, :mymeth){ 'stub-meth' }
38
- myobj.mymeth
39
- # => 'stub-meth'
40
- myobj.mymeth(123)
39
+ MuchStub.(my_object, :my_method)
40
+ my_object.my_method
41
+ # => StubError: `my_method` not stubbed.
42
+ MuchStub.(my_object, :my_method){ "stubbed-method" }
43
+ my_object.my_method
44
+ # => "stubbed-method"
45
+ my_object.my_method(123)
41
46
  # => StubError: arity mismatch
42
- MuchStub.(myobj, :mymeth).with(123){ 'stub-meth' }
47
+ MuchStub.(my_object, :my_method).with(123){ "stubbed-method" }
43
48
  # => StubError: arity mismatch
44
- MuchStub.stub_send(myobj, :mymeth) # call to the original method post-stub
45
- # => 'meth'
46
49
 
47
- # Create a new stub for the :myval method
50
+ # Call the original method after it has been stubbed.
51
+
52
+ MuchStub.stub_send(my_object, :my_method)
53
+ # => "my-method"
48
54
 
49
- MuchStub.(myobj, :myval){ 'stub-meth' }
55
+ # Create a new stub for the :my_value method
56
+
57
+ MuchStub.(my_object, :my_value){ "stubbed-method" }
50
58
  # => StubError: arity mismatch
51
- MuchStub.(myobj, :myval).with(123){ |val| val.to_s }
52
- myobj.myval
59
+ MuchStub.(my_object, :my_value).with(123){ |val| val.to_s }
60
+ my_object.my_value
53
61
  # => StubError: arity mismatch
54
- myobj.myval(123)
55
- # => '123'
56
- myobj.myval(456)
57
- # => StubError: `myval(456)` not stubbed.
62
+ my_object.my_value(123)
63
+ # => "123"
64
+ my_object.my_value(456)
65
+ # => StubError: `my_value(456)` not stubbed.
58
66
 
59
- # Call to the original method post-stub
67
+ # Call the original method after it has been stubbed.
60
68
 
61
- MuchStub.stub_send(myobj, :myval, 123)
69
+ MuchStub.stub_send(my_object, :my_value, 123)
62
70
  # => 123
63
- MuchStub.stub_send(myobj, :myval, 456)
71
+ MuchStub.stub_send(my_object, :my_value, 456)
64
72
  # => 456
65
73
 
66
74
  # Unstub individual stubs
67
75
 
68
- MuchStub.unstub(myobj, :mymeth)
69
- MuchStub.unstub(myobj, :myval)
76
+ MuchStub.unstub(my_object, :my_method)
77
+ MuchStub.unstub(my_object, :my_value)
70
78
 
71
79
  # OR blanket unstub all stubs
72
80
 
73
81
  MuchStub.unstub!
74
82
 
75
- # Original API is preserved after unstubbing
83
+ # The original API/behavior is preserved after unstubbing
76
84
 
77
- myobj.mymeth
78
- # => 'meth'
79
- myobj.myval(123)
85
+ my_object.my_method
86
+ # => "my-method"
87
+ my_object.my_value(123)
80
88
  # => 123
81
- myobj.myval(456)
89
+ my_object.my_value(456)
90
+ # => 456
91
+ ```
92
+
93
+ ### Stubs for spying
94
+
95
+ ```ruby
96
+ # Given this object/API
97
+
98
+ my_class = Class.new do
99
+ def basic_method(value)
100
+ value
101
+ end
102
+
103
+ def iterator_method(items, &block)
104
+ items.each(&block)
105
+ end
106
+ end
107
+ my_object = my_class.new
108
+
109
+ # Store method call arguments/blocks for spying.
110
+
111
+ basic_method_called_with = nil
112
+ MuchStub.(my_object, :basic_method) { |*args|
113
+ basic_method_called_with = args
114
+ }
115
+
116
+ my_object.basic_method(123)
117
+ basic_method_called_with
118
+ # => [123]
119
+
120
+ iterator_method_call_args = nil
121
+ iterator_method_call_block = nil
122
+ MuchStub.(my_object, :iterator_method) { |*args, &block|
123
+ iterator_method_call_args = args
124
+ iterator_method_call_block = block
125
+ }
126
+
127
+ my_object.iterator_method([1, 2, 3], &:to_s)
128
+ iterator_method_call_args
129
+ # => [[1, 2, 3]]
130
+ iterator_method_call_block
131
+ # => #<Proc:0x00007fb083a6feb0(&:to_s)>
132
+
133
+ # Count method calls for spying.
134
+
135
+ basic_method_call_count = 0
136
+ MuchStub.(my_object, :basic_method) {
137
+ basic_method_call_count += 1
138
+ }
139
+
140
+ my_object.basic_method(123)
141
+ basic_method_call_count
142
+ # => 1
143
+
144
+ # Count method calls and store arguments for spying.
145
+
146
+ basic_method_calls = []
147
+ MuchStub.(my_object, :basic_method) { |*args|
148
+ basic_method_calls << args
149
+ }
150
+
151
+ my_object.basic_method(123)
152
+ basic_method_calls.size
153
+ # => 1
154
+ basic_method_calls.first
155
+ # => [123]
156
+ ```
157
+
158
+ ### Stubs for test doubles.
159
+
160
+ ```ruby
161
+ # Given this object/API ...
162
+
163
+ my_class = Class.new do
164
+ def build_thing(thing_value);
165
+ Thing.new(value)
166
+ end
167
+ end
168
+ my_object = my_class.new
169
+
170
+ # ... and this Test Double.
171
+ class FakeThing
172
+ attr_reader :built_with
173
+
174
+ def initialize(*args)
175
+ @built_with = args
176
+ end
177
+ end
178
+
179
+ # Stub in the test double.
180
+
181
+ MuchStub.(my_object, :build_thing) { |*args|
182
+ FakeThing.new(*args)
183
+ }
184
+
185
+ thing = my_object.build_thing(123)
186
+ thing.built_with
187
+ # => [123]
188
+ ```
189
+
190
+ ### `MuchStub.tap`
191
+
192
+ Use the `.tap` method to spy on method calls while preserving the original method return value and behavior.
193
+
194
+ ```ruby
195
+ # Given this object/API
196
+
197
+ my_class = Class.new do
198
+ def basic_method(value)
199
+ value.to_s
200
+ end
201
+ end
202
+ my_object = my_class.new
203
+
204
+ # Normal stubs override the original behavior and return value...
205
+ basic_method_called_with = nil
206
+ MuchStub.(my_object, :basic_method) { |*args|
207
+ basic_method_called_with = args
208
+ }
209
+
210
+ # ... in this case not converting the value to a String and returning it and
211
+ # instead returning the arguments passed to the method.
212
+ my_object.basic_method(123)
213
+ # => [123]
214
+ basic_method_called_with
215
+ # => [123]
216
+
217
+ # Use `MuchStub.tap` to preserve the methods behavior and also spy.
218
+
219
+ basic_method_called_with = nil
220
+ MuchStub.tap(my_object, :basic_method) { |value, *args|
221
+ basic_method_called_with = args
222
+ }
223
+
224
+ my_object.basic_method(123)
225
+ # => "123"
226
+ basic_method_called_with
227
+ # => [123]
228
+ ```
229
+
230
+ #### Late-bound stubs using `MuchStub.tap`
231
+
232
+ Use the `.tap` method to stub any return values of method calls.
233
+
234
+ ```ruby
235
+ # Given:
236
+
237
+ class Thing
238
+ attr_reader :value
239
+
240
+ def initialize(value)
241
+ @value = value
242
+ end
243
+ end
244
+
245
+ my_class = Class.new do
246
+ def thing(value)
247
+ Thing.new(value)
248
+ end
249
+ end
250
+ my_object = my_class.new
251
+
252
+ # Use `MuchStub.tap` to stub any thing instances created by `my_object.thing`
253
+ # (and also spy on the call arguments)
254
+
255
+ thing_built_with = nil
256
+ MuchStub.tap(my_object, :thing) { |thing, *args|
257
+ thing_built_with = args
258
+ MuchStub.(thing, :value) { 456 }
259
+ }
260
+
261
+ thing = my_object.thing(123)
262
+ # => #<Thing:0x00007fd5ca9df510 @value=123>
263
+ thing_built_with
264
+ # => [123]
265
+ thing.value
82
266
  # => 456
83
267
  ```
84
268
 
@@ -86,7 +270,7 @@ myobj.myval(456)
86
270
 
87
271
  Add this line to your application's Gemfile:
88
272
 
89
- gem 'much-stub'
273
+ gem "much-stub"
90
274
 
91
275
  And then execute:
92
276
 
@@ -100,6 +284,6 @@ Or install it yourself as:
100
284
 
101
285
  1. Fork it
102
286
  2. Create your feature branch (`git checkout -b my-new-feature`)
103
- 3. Commit your changes (`git commit -am 'Added some feature'`)
287
+ 3. Commit your changes (`git commit -am "Added some feature"`)
104
288
  4. Push to the branch (`git push origin my-new-feature`)
105
289
  5. Create new Pull Request
@@ -1,7 +1,6 @@
1
1
  require "much-stub/version"
2
2
 
3
3
  module MuchStub
4
-
5
4
  def self.stubs
6
5
  @stubs ||= {}
7
6
  end
@@ -37,8 +36,15 @@ module MuchStub
37
36
  stub.call_method(args, &block)
38
37
  end
39
38
 
40
- class Stub
39
+ def self.tap(obj, meth, &tap_block)
40
+ self.stub(obj, meth) { |*args, &block|
41
+ self.stub_send(obj, meth, *args, &block).tap { |value|
42
+ tap_block.call(value, *args, &block) if tap_block
43
+ }
44
+ }
45
+ end
41
46
 
47
+ class Stub
42
48
  def self.key(object, method_name)
43
49
  "--#{object.object_id}--#{method_name}--"
44
50
  end
@@ -100,7 +106,7 @@ module MuchStub
100
106
  end
101
107
 
102
108
  def inspect
103
- "#<#{self.class}:#{'0x0%x' % (object_id << 1)}" \
109
+ "#<#{self.class}:#{"0x0%x" % (object_id << 1)}" \
104
110
  " @method_name=#{@method_name.inspect}" \
105
111
  ">"
106
112
  end
@@ -159,7 +165,7 @@ module MuchStub
159
165
  end
160
166
 
161
167
  def inspect_call(args)
162
- "`#{@method_name}(#{args.map(&:inspect).join(',')})`"
168
+ "`#{@method_name}(#{args.map(&:inspect).join(",")})`"
163
169
  end
164
170
 
165
171
  def number_of_args(arity)
@@ -169,7 +175,6 @@ module MuchStub
169
175
  arity
170
176
  end
171
177
  end
172
-
173
178
  end
174
179
 
175
180
  StubError = Class.new(ArgumentError)
@@ -181,15 +186,14 @@ module MuchStub
181
186
  end
182
187
 
183
188
  module ParameterList
184
-
185
- LETTERS = ('a'..'z').to_a.freeze
189
+ LETTERS = ("a".."z").to_a.freeze
186
190
 
187
191
  def self.new(object, method_name)
188
192
  arity = get_arity(object, method_name)
189
193
  params = build_params_from_arity(arity)
190
- params << '*args' if arity < 0
191
- params << '&block'
192
- params.join(', ')
194
+ params << "*args" if arity < 0
195
+ params << "&block"
196
+ params.join(", ")
193
197
  end
194
198
 
195
199
  private
@@ -210,9 +214,7 @@ module MuchStub
210
214
  number_of_letters, letter_index = param_index.divmod(LETTERS.size)
211
215
  LETTERS[letter_index] * number_of_letters
212
216
  end
213
-
214
217
  end
215
-
216
218
  end
217
219
 
218
220
  # Kernel#caller_locations polyfill for pre ruby 2.0.0
@@ -1,3 +1,3 @@
1
1
  module MuchStub
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -1,5 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
- lib = File.expand_path('../lib', __FILE__)
2
+ lib = File.expand_path("../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require "much-stub/version"
5
5
 
@@ -11,13 +11,13 @@ Gem::Specification.new do |gem|
11
11
  gem.summary = "Stubbing API for replacing method calls on objects in test runs."
12
12
  gem.description = "Stubbing API for replacing method calls on objects in test runs."
13
13
  gem.homepage = "https://github.com/redding/much-stub"
14
- gem.license = 'MIT'
14
+ gem.license = "MIT"
15
15
 
16
16
  gem.files = `git ls-files`.split($/)
17
17
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
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.17.0"])
21
+ gem.add_development_dependency("assert", ["~> 2.18.0"])
22
22
 
23
23
  end
@@ -5,9 +5,9 @@
5
5
  $LOAD_PATH.unshift(File.expand_path("../..", __FILE__))
6
6
 
7
7
  # require pry for debugging (`binding.pry`)
8
- require 'pry'
8
+ require "pry"
9
9
 
10
- require 'test/support/factory'
10
+ require "test/support/factory"
11
11
 
12
12
  # 1.8.7 backfills
13
13
 
@@ -19,7 +19,7 @@ if !(a = Array.new).respond_to?(:sample) && a.respond_to?(:choice)
19
19
  end
20
20
 
21
21
  # unstub all test stubs automatically for Assert test suite
22
- require 'assert'
22
+ require "assert"
23
23
  class Assert::Context
24
24
  teardown{ MuchStub.unstub! }
25
25
  end