much-stub 0.1.1 → 0.1.2

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: 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