grift 2.0.1 → 2.2.0
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/.github/FUNDING.yml +3 -0
- data/.github/workflows/ci.yml +6 -6
- data/.rubocop.yml +9 -2
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +35 -27
- data/README.md +1 -2
- data/lib/grift/mock_method.rb +263 -17
- data/lib/grift/version.rb +1 -1
- metadata +7 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: aa5b5344bca43ca62082d11f90cea53e27b02ee4defc424916aa7ffa123099f0
|
|
4
|
+
data.tar.gz: dcc8fe58f1f753b15dc040a2663467d159de298bf08b51177d61652ac6105a9f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cc2aa7d33cfd5296bc24a8fb10d5dc678c3b71781d9ff63a7c475055997310a41fa6963ff351c14384a321224ba3bbf2159b2ae94c06ce03b5997725da46f1ae
|
|
7
|
+
data.tar.gz: 2809aeaf6fde5122e733e0dd25e84d9989051b9e5d25ca7d2593e77b005785182bede7d0caf81e7743f500d389f834c4fa67b89a28d7e85d10ed4cb3f0c29006
|
data/.github/FUNDING.yml
ADDED
data/.github/workflows/ci.yml
CHANGED
|
@@ -15,12 +15,12 @@ jobs:
|
|
|
15
15
|
BUNDLE_WITHOUT: development:test
|
|
16
16
|
|
|
17
17
|
steps:
|
|
18
|
-
- uses: actions/checkout@
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
19
|
|
|
20
|
-
- name: Set up Ruby
|
|
20
|
+
- name: Set up Ruby 3.3
|
|
21
21
|
uses: ruby/setup-ruby@v1
|
|
22
22
|
with:
|
|
23
|
-
ruby-version:
|
|
23
|
+
ruby-version: 3.3
|
|
24
24
|
bundler-cache: true
|
|
25
25
|
|
|
26
26
|
- name: Rubocop
|
|
@@ -33,10 +33,10 @@ jobs:
|
|
|
33
33
|
strategy:
|
|
34
34
|
fail-fast: false
|
|
35
35
|
matrix:
|
|
36
|
-
ruby: ["2.7", "3.0", "3.1"]
|
|
36
|
+
ruby: ["2.7", "3.0", "3.1", "3.2", "3.3"]
|
|
37
37
|
|
|
38
38
|
steps:
|
|
39
|
-
- uses: actions/checkout@
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
40
|
- uses: ruby/setup-ruby@v1
|
|
41
41
|
with:
|
|
42
42
|
ruby-version: ${{ matrix.ruby }}
|
|
@@ -47,7 +47,7 @@ jobs:
|
|
|
47
47
|
run: bundle exec rake test
|
|
48
48
|
|
|
49
49
|
- name: Upload coverage to Codecov
|
|
50
|
-
uses: codecov/codecov-action@
|
|
50
|
+
uses: codecov/codecov-action@v3
|
|
51
51
|
with:
|
|
52
52
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
53
53
|
files: ./coverage/.resultset.json
|
data/.rubocop.yml
CHANGED
|
@@ -102,12 +102,12 @@ Lint/AmbiguousRange:
|
|
|
102
102
|
|
|
103
103
|
# Metrics
|
|
104
104
|
Metrics/AbcSize:
|
|
105
|
-
Max:
|
|
105
|
+
Max: 25
|
|
106
106
|
Exclude:
|
|
107
107
|
- "test/**/*"
|
|
108
108
|
|
|
109
109
|
Metrics/ClassLength:
|
|
110
|
-
Max:
|
|
110
|
+
Max: 225
|
|
111
111
|
CountAsOne:
|
|
112
112
|
- array
|
|
113
113
|
- hash
|
|
@@ -128,6 +128,9 @@ Metrics/MethodLength:
|
|
|
128
128
|
Minitest/AssertPredicate:
|
|
129
129
|
Enabled: false
|
|
130
130
|
|
|
131
|
+
Minitest/EmptyLineBeforeAssertionMethods:
|
|
132
|
+
Enabled: false
|
|
133
|
+
|
|
131
134
|
Minitest/MultipleAssertions:
|
|
132
135
|
Max: 10
|
|
133
136
|
|
|
@@ -138,6 +141,10 @@ Minitest/RefutePredicate:
|
|
|
138
141
|
Naming/InclusiveLanguage:
|
|
139
142
|
Enabled: true
|
|
140
143
|
|
|
144
|
+
Naming/MethodParameterName:
|
|
145
|
+
AllowedNames:
|
|
146
|
+
- n
|
|
147
|
+
|
|
141
148
|
Naming/VariableNumber:
|
|
142
149
|
EnforcedStyle: snake_case
|
|
143
150
|
|
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,21 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
8
8
|
|
|
9
9
|
None
|
|
10
10
|
|
|
11
|
+
## [2.2.0](https://github.com/clarkedb/grift/releases/tag/v2.2.0) - 2024-01-13
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
* Official support for Ruby 3.3 ([#203](https://github.com/clarkedb/grift/pull/203))
|
|
16
|
+
|
|
17
|
+
## [2.1.0](https://github.com/clarkedb/grift/releases/tag/v2.1.0) - 2022-12-27
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
* Official support for Ruby 3.2 ([#126](https://github.com/clarkedb/grift/pull/126))
|
|
22
|
+
* Support for finite/self-terminating mocking for more precision in testing where a method may get called multiple times
|
|
23
|
+
+ The Grift API now supports `mock_return_value_once`, `mock_return_value_n_times`, and `mock_return_values_in_order` ([#135](https://github.com/clarkedb/grift/pull/135))
|
|
24
|
+
+ The Grift API now supports `mock_implementation_once` and `mock_implementation_n_times` ([#136](https://github.com/clarkedb/grift/pull/136))
|
|
25
|
+
|
|
11
26
|
## [2.0.1](https://github.com/clarkedb/grift/releases/tag/v2.0.1) - 2022-03-27
|
|
12
27
|
|
|
13
28
|
### Fixed
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
grift (2.0
|
|
4
|
+
grift (2.2.0)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
@@ -10,53 +10,61 @@ GEM
|
|
|
10
10
|
ast (2.4.2)
|
|
11
11
|
builder (3.2.4)
|
|
12
12
|
childprocess (4.1.0)
|
|
13
|
-
codecov (0.
|
|
14
|
-
|
|
13
|
+
codecov (0.2.12)
|
|
14
|
+
json
|
|
15
|
+
simplecov
|
|
15
16
|
docile (1.4.0)
|
|
16
17
|
iniparse (1.5.0)
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
json (2.7.1)
|
|
19
|
+
language_server-protocol (3.17.0.3)
|
|
20
|
+
minitest (5.20.0)
|
|
21
|
+
minitest-reporters (1.6.1)
|
|
19
22
|
ansi
|
|
20
23
|
builder
|
|
21
24
|
minitest (>= 5.0)
|
|
22
25
|
ruby-progressbar
|
|
23
|
-
overcommit (0.
|
|
26
|
+
overcommit (0.60.0)
|
|
24
27
|
childprocess (>= 0.6.3, < 5)
|
|
25
28
|
iniparse (~> 1.4)
|
|
26
29
|
rexml (~> 3.2)
|
|
27
|
-
parallel (1.
|
|
28
|
-
parser (3.
|
|
30
|
+
parallel (1.24.0)
|
|
31
|
+
parser (3.3.0.3)
|
|
29
32
|
ast (~> 2.4.1)
|
|
33
|
+
racc
|
|
34
|
+
racc (1.7.3)
|
|
30
35
|
rainbow (3.1.1)
|
|
31
|
-
rake (13.0
|
|
32
|
-
regexp_parser (2.
|
|
33
|
-
rexml (3.2.
|
|
34
|
-
rubocop (1.
|
|
36
|
+
rake (13.1.0)
|
|
37
|
+
regexp_parser (2.9.0)
|
|
38
|
+
rexml (3.2.6)
|
|
39
|
+
rubocop (1.59.0)
|
|
40
|
+
json (~> 2.3)
|
|
41
|
+
language_server-protocol (>= 3.17.0)
|
|
35
42
|
parallel (~> 1.10)
|
|
36
|
-
parser (>= 3.
|
|
43
|
+
parser (>= 3.2.2.4)
|
|
37
44
|
rainbow (>= 2.2.2, < 4.0)
|
|
38
45
|
regexp_parser (>= 1.8, < 3.0)
|
|
39
|
-
rexml
|
|
40
|
-
rubocop-ast (>= 1.
|
|
46
|
+
rexml (>= 3.2.5, < 4.0)
|
|
47
|
+
rubocop-ast (>= 1.30.0, < 2.0)
|
|
41
48
|
ruby-progressbar (~> 1.7)
|
|
42
|
-
unicode-display_width (>=
|
|
43
|
-
rubocop-ast (1.
|
|
44
|
-
parser (>= 3.
|
|
45
|
-
rubocop-minitest (0.
|
|
46
|
-
rubocop (>=
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
|
50
|
+
rubocop-ast (1.30.0)
|
|
51
|
+
parser (>= 3.2.1.0)
|
|
52
|
+
rubocop-minitest (0.34.4)
|
|
53
|
+
rubocop (>= 1.39, < 2.0)
|
|
54
|
+
rubocop-ast (>= 1.30.0, < 2.0)
|
|
55
|
+
rubocop-packaging (0.5.2)
|
|
56
|
+
rubocop (>= 1.33, < 2.0)
|
|
57
|
+
rubocop-performance (1.19.1)
|
|
50
58
|
rubocop (>= 1.7.0, < 2.0)
|
|
51
59
|
rubocop-ast (>= 0.4.0)
|
|
52
|
-
ruby-progressbar (1.
|
|
53
|
-
simplecov (0.
|
|
60
|
+
ruby-progressbar (1.13.0)
|
|
61
|
+
simplecov (0.22.0)
|
|
54
62
|
docile (~> 1.1)
|
|
55
63
|
simplecov-html (~> 0.11)
|
|
56
64
|
simplecov_json_formatter (~> 0.1)
|
|
57
65
|
simplecov-html (0.12.3)
|
|
58
|
-
simplecov_json_formatter (0.1.
|
|
59
|
-
unicode-display_width (2.
|
|
66
|
+
simplecov_json_formatter (0.1.4)
|
|
67
|
+
unicode-display_width (2.5.0)
|
|
60
68
|
|
|
61
69
|
PLATFORMS
|
|
62
70
|
ruby
|
data/README.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Grift
|
|
2
2
|
|
|
3
3
|
[](https://rubygems.org/gems/grift)
|
|
4
|
-
[](https://rubygems.org/gems/grift)
|
|
5
4
|
[](https://github.com/clarkedb/grift/actions?query=workflow%3ACI)
|
|
6
5
|
[](https://codecov.io/gh/clarkedb/grift)
|
|
7
6
|
|
|
@@ -123,7 +122,7 @@ my_mock.mock.results
|
|
|
123
122
|
|
|
124
123
|
## Requirements
|
|
125
124
|
|
|
126
|
-
Grift supports all Ruby versions >= 2.7 (including 3.
|
|
125
|
+
Grift supports all Ruby versions >= 2.7 (including 3.3).
|
|
127
126
|
|
|
128
127
|
## Development
|
|
129
128
|
|
data/lib/grift/mock_method.rb
CHANGED
|
@@ -11,6 +11,22 @@ module Grift
|
|
|
11
11
|
CACHE_METHOD_PREFIX = 'grift_cache'
|
|
12
12
|
private_constant :CACHE_METHOD_PREFIX
|
|
13
13
|
|
|
14
|
+
##
|
|
15
|
+
# Hashes the class and method for tracking mocks.
|
|
16
|
+
#
|
|
17
|
+
# @example
|
|
18
|
+
# Grift::MockMethod.hash_key(String, :upcase)
|
|
19
|
+
# #=> 'String#upcase'
|
|
20
|
+
#
|
|
21
|
+
# @param klass [Class]
|
|
22
|
+
# @param method_name [Symbol]
|
|
23
|
+
#
|
|
24
|
+
# @return [String] the hash of the class and method
|
|
25
|
+
#
|
|
26
|
+
def self.hash_key(klass, method_name)
|
|
27
|
+
"#{klass}##{method_name}"
|
|
28
|
+
end
|
|
29
|
+
|
|
14
30
|
##
|
|
15
31
|
# A new instance of MockMethod. Should be initialized via {Grift.mock} or {Grift.spy_on}
|
|
16
32
|
#
|
|
@@ -36,7 +52,7 @@ module Grift
|
|
|
36
52
|
@method_name = method_name
|
|
37
53
|
@true_method_cached = false
|
|
38
54
|
@mock_executions = MockExecutions.new
|
|
39
|
-
@cache_method_name = "#{CACHE_METHOD_PREFIX}_#{method_name}"
|
|
55
|
+
@cache_method_name = :"#{CACHE_METHOD_PREFIX}_#{method_name}"
|
|
40
56
|
|
|
41
57
|
# class methods are really instance methods of the singleton class
|
|
42
58
|
@class_method = klass.singleton_class.method_defined?(method_name, true) ||
|
|
@@ -145,7 +161,116 @@ module Grift
|
|
|
145
161
|
|
|
146
162
|
# record the args passed in the call to the method and the result
|
|
147
163
|
mock_executions.store(args: args, result: return_value)
|
|
148
|
-
|
|
164
|
+
return_value
|
|
165
|
+
end
|
|
166
|
+
class_instance.send(@method_access, @method_name)
|
|
167
|
+
|
|
168
|
+
self
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
##
|
|
172
|
+
# Accepts a block and mocks the method to execute that block instead
|
|
173
|
+
# of the original behavior the next time the method is called while mocked.
|
|
174
|
+
# After the method has been called once, it will return to its original
|
|
175
|
+
# behavior. The method will continue to be watched.
|
|
176
|
+
#
|
|
177
|
+
# @see #mock_implementation
|
|
178
|
+
#
|
|
179
|
+
# @example
|
|
180
|
+
# my_mock = Grift.spy_on(String, :downcase).mock_implementation_once do
|
|
181
|
+
# x = 3 + 4
|
|
182
|
+
# x.to_s
|
|
183
|
+
# end
|
|
184
|
+
# ["Banana", "Apple"].map(&:downcase)
|
|
185
|
+
# #=> ["7", "apple"]
|
|
186
|
+
#
|
|
187
|
+
# @return [self] the mock itself
|
|
188
|
+
#
|
|
189
|
+
def mock_implementation_once(*)
|
|
190
|
+
raise(Grift::Error, 'Must provide a block for the new implementation') unless block_given?
|
|
191
|
+
|
|
192
|
+
premock_setup
|
|
193
|
+
|
|
194
|
+
# required to access inside class instance block
|
|
195
|
+
mock_executions = @mock_executions
|
|
196
|
+
clean_mock = lambda do
|
|
197
|
+
unmock_method
|
|
198
|
+
watch_method
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
class_instance.remove_method(@method_name) if !@inherited && method_defined?
|
|
202
|
+
class_instance.define_method @method_name do |*args, **kwargs|
|
|
203
|
+
return_value = yield(*args, **kwargs)
|
|
204
|
+
|
|
205
|
+
# record the args passed in the call to the method and the result
|
|
206
|
+
mock_executions.store(args: args, result: return_value)
|
|
207
|
+
|
|
208
|
+
clean_mock.call
|
|
209
|
+
|
|
210
|
+
return_value
|
|
211
|
+
end
|
|
212
|
+
class_instance.send(@method_access, @method_name)
|
|
213
|
+
|
|
214
|
+
self
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
##
|
|
218
|
+
# Accepts a number +n+ and a block and mocks the method to execute that block
|
|
219
|
+
# instaead of the original behavior the next +n+ times the method is called
|
|
220
|
+
# while mocked. After the method has been called once, it will return to its
|
|
221
|
+
# original behavior. The method will continue to be watched.
|
|
222
|
+
#
|
|
223
|
+
# **IMPORANT:** Calling {#mock_clear} clears the method call history. If it is
|
|
224
|
+
# called before the nth execution of the mocked method, the method will remain
|
|
225
|
+
# mocked for an additonal +n+ calls.
|
|
226
|
+
#
|
|
227
|
+
# @see #mock_implementation
|
|
228
|
+
#
|
|
229
|
+
# @example
|
|
230
|
+
# my_mock = Grift.spy_on(String, :downcase).mock_implementation_n_times(3) do
|
|
231
|
+
# x = 3 + 4
|
|
232
|
+
# x.to_s
|
|
233
|
+
# end
|
|
234
|
+
# ["Banana", "Apple", "Orange", "Guava"].map(&:downcase)
|
|
235
|
+
# #=> ["7", "7", "7", "guava"]
|
|
236
|
+
#
|
|
237
|
+
# @example
|
|
238
|
+
# my_mock = Grift.spy_on(String, :downcase).mock_implementation_n_times(5) do
|
|
239
|
+
# x = 3 + 4
|
|
240
|
+
# x.to_s
|
|
241
|
+
# end
|
|
242
|
+
# ["Banana", "Apple", "Orange", "Guava"].map(&:downcase)
|
|
243
|
+
# #=> ["7", "7", "7", "7"]
|
|
244
|
+
# my_mock.mock_clear # clear mock history before 5th (nth) method call
|
|
245
|
+
# ["Banana", "Apple", "Orange", "Guava"].map(&:downcase)
|
|
246
|
+
# #=> ["7", "7", "7", "7"]
|
|
247
|
+
#
|
|
248
|
+
# @param n [Number] the number of times to mock the implementation
|
|
249
|
+
#
|
|
250
|
+
# @return [self] the mock itself
|
|
251
|
+
#
|
|
252
|
+
def mock_implementation_n_times(n, *)
|
|
253
|
+
raise(Grift::Error, 'Must provide a block for the new implementation') unless block_given?
|
|
254
|
+
|
|
255
|
+
premock_setup
|
|
256
|
+
|
|
257
|
+
# required to access inside class instance block
|
|
258
|
+
mock_executions = @mock_executions
|
|
259
|
+
clean_mock = lambda do
|
|
260
|
+
unmock_method
|
|
261
|
+
watch_method
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
class_instance.remove_method(@method_name) if !@inherited && method_defined?
|
|
265
|
+
class_instance.define_method @method_name do |*args, **kwargs|
|
|
266
|
+
return_value = yield(*args, **kwargs)
|
|
267
|
+
|
|
268
|
+
# record the args passed in the call to the method and the result
|
|
269
|
+
mock_executions.store(args: args, result: return_value)
|
|
270
|
+
|
|
271
|
+
clean_mock.call if mock_executions.count == n
|
|
272
|
+
|
|
273
|
+
return_value
|
|
149
274
|
end
|
|
150
275
|
class_instance.send(@method_access, @method_name)
|
|
151
276
|
|
|
@@ -175,7 +300,7 @@ module Grift
|
|
|
175
300
|
class_instance.define_method @method_name do |*args, **kwargs|
|
|
176
301
|
# record the args passed in the call to the method and the result
|
|
177
302
|
mock_executions.store(args: args, kwargs: kwargs, result: return_value)
|
|
178
|
-
|
|
303
|
+
return_value
|
|
179
304
|
end
|
|
180
305
|
class_instance.send(@method_access, @method_name)
|
|
181
306
|
|
|
@@ -183,30 +308,151 @@ module Grift
|
|
|
183
308
|
end
|
|
184
309
|
|
|
185
310
|
##
|
|
186
|
-
#
|
|
311
|
+
# Accepts a value and mocks the method to return that value once instead
|
|
312
|
+
# of executing its original behavior while mocked. After the method has
|
|
313
|
+
# been called once, it will return to its original behavior. The method
|
|
314
|
+
# will continue to be watched.
|
|
187
315
|
#
|
|
188
|
-
# @
|
|
316
|
+
# @example
|
|
317
|
+
# my_mock = Grift.spy_on(String, :upcase).mock_return_value_once("BANANA")
|
|
318
|
+
# ["apple", "apple"].map(&:upcase)
|
|
319
|
+
# #=> ["BANANA", "APPLE"]
|
|
189
320
|
#
|
|
190
|
-
# @return
|
|
321
|
+
# @param return_value the value to return from the method once
|
|
191
322
|
#
|
|
192
|
-
|
|
193
|
-
|
|
323
|
+
# @return [self] the mock itself
|
|
324
|
+
#
|
|
325
|
+
def mock_return_value_once(return_value = nil)
|
|
326
|
+
premock_setup
|
|
327
|
+
|
|
328
|
+
# required to access mock inside class instance block
|
|
329
|
+
mock_executions = @mock_executions
|
|
330
|
+
clean_mock = lambda do
|
|
331
|
+
unmock_method
|
|
332
|
+
watch_method
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
class_instance.remove_method(@method_name) if !@inherited && method_defined?
|
|
336
|
+
class_instance.define_method @method_name do |*args, **kwargs|
|
|
337
|
+
# record the args passed in the call to the method and the result
|
|
338
|
+
mock_executions.store(args: args, kwargs: kwargs, result: return_value)
|
|
339
|
+
|
|
340
|
+
clean_mock.call
|
|
341
|
+
|
|
342
|
+
return_value
|
|
343
|
+
end
|
|
344
|
+
class_instance.send(@method_access, @method_name)
|
|
345
|
+
|
|
346
|
+
self
|
|
194
347
|
end
|
|
195
348
|
|
|
196
349
|
##
|
|
197
|
-
#
|
|
350
|
+
# Accepts a value and mocks the method to return that value +n+ times instead
|
|
351
|
+
# of executing its original behavior while mocked. After the method has
|
|
352
|
+
# been called +n+ times, it will return to its original behavior. The method
|
|
353
|
+
# will continue to be watched.
|
|
354
|
+
#
|
|
355
|
+
# **IMPORANT:** Calling {#mock_clear} clears the method call history. If it is
|
|
356
|
+
# called before the nth execution of the mocked method, the method will remain
|
|
357
|
+
# mocked for an additional +n+ calls.
|
|
198
358
|
#
|
|
199
359
|
# @example
|
|
200
|
-
# Grift
|
|
201
|
-
#
|
|
360
|
+
# my_mock = Grift.spy_on(String, :upcase).mock_return_value_n_times(2, "BANANA")
|
|
361
|
+
# ["apple", "apple", "apple"].map(&:upcase)
|
|
362
|
+
# #=> ["BANANA", "BANANA", "APPLE"]
|
|
202
363
|
#
|
|
203
|
-
# @
|
|
204
|
-
#
|
|
364
|
+
# @example
|
|
365
|
+
# my_mock = Grift.spy_on(String, :upcase).mock_return_value_n_times(4, "BANANA")
|
|
366
|
+
# ["apple", "apple", "apple"].map(&:upcase)
|
|
367
|
+
# #=> ["BANANA", "BANANA", "BANANA"]
|
|
368
|
+
# my_mock.mock_clear # clear mock history before 4th (nth) method call
|
|
369
|
+
# ["apple", "apple", "apple"].map(&:upcase)
|
|
370
|
+
# #=> ["BANANA", "BANANA", "BANANA"]
|
|
205
371
|
#
|
|
206
|
-
# @
|
|
372
|
+
# @param n [Number] the number of times to mock the return value
|
|
373
|
+
# @param return_value the value to return from the method +n+ times
|
|
207
374
|
#
|
|
208
|
-
|
|
209
|
-
|
|
375
|
+
# @return [self] the mock itself
|
|
376
|
+
#
|
|
377
|
+
def mock_return_value_n_times(n, return_value = nil)
|
|
378
|
+
premock_setup
|
|
379
|
+
|
|
380
|
+
# required to access mock inside class instance block
|
|
381
|
+
mock_executions = @mock_executions
|
|
382
|
+
clean_mock = lambda do
|
|
383
|
+
unmock_method
|
|
384
|
+
watch_method
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
class_instance.remove_method(@method_name) if !@inherited && method_defined?
|
|
388
|
+
class_instance.define_method @method_name do |*args, **kwargs|
|
|
389
|
+
# record the args passed in the call to the method and the result
|
|
390
|
+
mock_executions.store(args: args, kwargs: kwargs, result: return_value)
|
|
391
|
+
|
|
392
|
+
clean_mock.call if mock_executions.count == n
|
|
393
|
+
|
|
394
|
+
return_value
|
|
395
|
+
end
|
|
396
|
+
class_instance.send(@method_access, @method_name)
|
|
397
|
+
|
|
398
|
+
self
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
##
|
|
402
|
+
# Accepts an array of values and mocks the method to return those values
|
|
403
|
+
# in order instead of executing its original behavior while mocked. After
|
|
404
|
+
# the method has been called enough times to return each of the values,
|
|
405
|
+
# it will return to its original behavior. The method continue to be watched.
|
|
406
|
+
#
|
|
407
|
+
# @example
|
|
408
|
+
# mock_values = ["APPLE", "BANANA", "ORANGE"]
|
|
409
|
+
# my_mock = Grift.spy_on(String, :upcase).mock_return_values_in_order(mock_values)
|
|
410
|
+
# ["pineapple", "orange", "guava", "mango", "watermelon"].map(&:upcase)
|
|
411
|
+
# #=> ["APPLE", "BANANA", "ORANGE", "MANGO", "WATERMELON"]
|
|
412
|
+
#
|
|
413
|
+
# @param return_values [Array] the values to return from the method in order
|
|
414
|
+
#
|
|
415
|
+
# @return [self] the mock itself
|
|
416
|
+
#
|
|
417
|
+
def mock_return_values_in_order(return_values)
|
|
418
|
+
unless return_values.is_a?(Array) && !return_values.empty?
|
|
419
|
+
raise(Grift::Error, 'Must provide a non-empty array for the return values')
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
premock_setup
|
|
423
|
+
|
|
424
|
+
# required to access mock inside class instance block
|
|
425
|
+
mock_executions = @mock_executions
|
|
426
|
+
clean_mock = lambda do
|
|
427
|
+
unmock_method
|
|
428
|
+
watch_method
|
|
429
|
+
end
|
|
430
|
+
return_values_internal = return_values.dup
|
|
431
|
+
|
|
432
|
+
class_instance.remove_method(@method_name) if !@inherited && method_defined?
|
|
433
|
+
class_instance.define_method @method_name do |*args, **kwargs|
|
|
434
|
+
# record the args passed in the call to the method and the result
|
|
435
|
+
return_value = return_values_internal.shift
|
|
436
|
+
mock_executions.store(args: args, kwargs: kwargs, result: return_value)
|
|
437
|
+
|
|
438
|
+
clean_mock.call if return_values_internal.empty?
|
|
439
|
+
|
|
440
|
+
return_value
|
|
441
|
+
end
|
|
442
|
+
class_instance.send(@method_access, @method_name)
|
|
443
|
+
|
|
444
|
+
self
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
##
|
|
448
|
+
# String representation of the MockMethod
|
|
449
|
+
#
|
|
450
|
+
# @see Grift::MockMethod.hash_key
|
|
451
|
+
#
|
|
452
|
+
# @return [String]
|
|
453
|
+
#
|
|
454
|
+
def to_s
|
|
455
|
+
Grift::MockMethod.hash_key(@klass, @method_name)
|
|
210
456
|
end
|
|
211
457
|
|
|
212
458
|
private
|
|
@@ -227,7 +473,7 @@ module Grift
|
|
|
227
473
|
|
|
228
474
|
# record the args passed in the call to the method and the result
|
|
229
475
|
mock_executions.store(args: args, kwargs: kwargs, result: return_value)
|
|
230
|
-
|
|
476
|
+
return_value
|
|
231
477
|
end
|
|
232
478
|
class_instance.send(@method_access, @method_name)
|
|
233
479
|
|
data/lib/grift/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: grift
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0
|
|
4
|
+
version: 2.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Clark Brown
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-01-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A gem for simple mocking and spying in Ruby's MiniTest framework.
|
|
14
14
|
email:
|
|
@@ -19,6 +19,7 @@ extra_rdoc_files: []
|
|
|
19
19
|
files:
|
|
20
20
|
- ".github/CODEOWNERS"
|
|
21
21
|
- ".github/CONTRIBUTING.md"
|
|
22
|
+
- ".github/FUNDING.yml"
|
|
22
23
|
- ".github/dependabot.yml"
|
|
23
24
|
- ".github/workflows/ci.yml"
|
|
24
25
|
- ".gitignore"
|
|
@@ -54,7 +55,7 @@ metadata:
|
|
|
54
55
|
homepage_uri: https://github.com/clarkedb/grift
|
|
55
56
|
rubygems_mfa_required: 'true'
|
|
56
57
|
source_code_uri: https://github.com/clarkedb/grift
|
|
57
|
-
post_install_message:
|
|
58
|
+
post_install_message:
|
|
58
59
|
rdoc_options: []
|
|
59
60
|
require_paths:
|
|
60
61
|
- lib
|
|
@@ -69,8 +70,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
69
70
|
- !ruby/object:Gem::Version
|
|
70
71
|
version: '0'
|
|
71
72
|
requirements: []
|
|
72
|
-
rubygems_version: 3.
|
|
73
|
-
signing_key:
|
|
73
|
+
rubygems_version: 3.5.3
|
|
74
|
+
signing_key:
|
|
74
75
|
specification_version: 4
|
|
75
76
|
summary: Mocking and spying in MiniTest
|
|
76
77
|
test_files: []
|