grift 2.0.0 → 2.1.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/workflows/ci.yml +6 -6
- data/.rubocop.yml +9 -2
- data/CHANGELOG.md +19 -1
- data/Gemfile.lock +24 -21
- data/README.md +2 -2
- data/lib/grift/mock_method.rb +254 -6
- data/lib/grift/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: be076a2312ee3278d68f393d8ace60b12aa44cec9923336fbe0469366be5c9cd
|
|
4
|
+
data.tar.gz: b38846285534aaf9e56c413c77b84da307655a1ac336aba9c8a4fa3b676a34c7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 25cdd247a6c4eacff1c77b099d22475bedb56d7a885beb1365e71e6798bddee87401fe1257e65cfbb5af5137b8458af650f2916f32b000a0712c3494e3f45459
|
|
7
|
+
data.tar.gz: 2c0e207ea0c7eb8db2719af429aaf0831fcb18169f5167d92f0111207e5a228e9f2a5d49131565dd499043268b65c4481fbd4497dca918c993326d7ed683102f
|
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@v3
|
|
19
19
|
|
|
20
|
-
- name: Set up Ruby
|
|
20
|
+
- name: Set up Ruby 3.1
|
|
21
21
|
uses: ruby/setup-ruby@v1
|
|
22
22
|
with:
|
|
23
|
-
ruby-version:
|
|
23
|
+
ruby-version: 3.1
|
|
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"]
|
|
37
37
|
|
|
38
38
|
steps:
|
|
39
|
-
- uses: actions/checkout@
|
|
39
|
+
- uses: actions/checkout@v3
|
|
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,8 +8,26 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
8
8
|
|
|
9
9
|
None
|
|
10
10
|
|
|
11
|
+
## [2.1.0](https://github.com/clarkedb/grift/releases/tag/v2.1.0) - 2022-12-27
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
* Official support for Ruby 3.2 ([#126](https://github.com/clarkedb/grift/pull/126))
|
|
16
|
+
* Support for finite/self-terminating mocking for more precision in testing where a method may get called multiple times
|
|
17
|
+
+ 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))
|
|
18
|
+
+ The Grift API now supports `mock_implementation_once` and `mock_implementation_n_times` ([#136](https://github.com/clarkedb/grift/pull/136))
|
|
19
|
+
|
|
20
|
+
## [2.0.1](https://github.com/clarkedb/grift/releases/tag/v2.0.1) - 2022-03-27
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
* When spying on a method that takes a block, the block now gets forwarded to the original method ([#78](https://github.com/clarkedb/grift/pull/78))
|
|
25
|
+
* When mocking the implementation, if a block is not provided a `Grift::Error` is raised instead of a `LocalJumpError` ([#77](https://github.com/clarkedb/grift/pull/77))
|
|
26
|
+
|
|
11
27
|
## [2.0.0](https://github.com/clarkedb/grift/releases/tag/v2.0.0) - 2022-03-14
|
|
12
28
|
|
|
29
|
+
This version adds true keyword argument support for Ruby 3. See below for how to handle breaking changes.
|
|
30
|
+
|
|
13
31
|
### Changed
|
|
14
32
|
|
|
15
33
|
* Dropped support for Ruby 2.5 ([#69](https://github.com/clarkedb/grift/pull/69))
|
|
@@ -17,7 +35,7 @@ None
|
|
|
17
35
|
* To support keyword arguments, records of call arguments are no longer stored in simple arrays but in a custom Enumerable ([#72](https://github.com/clarkedb/grift/pull/72))
|
|
18
36
|
+ This changes the way that your tests will interact with mock calls
|
|
19
37
|
+ When before `calls` returned an array, it returns a `Grift::MockMethod::MockExecutions::MockArguments` object
|
|
20
|
-
+ Migrating to maintain previous behavior just requires appending `.args` to `calls`
|
|
38
|
+
+ Migrating to maintain previous behavior just requires appending `.args` to `calls[i]`
|
|
21
39
|
|
|
22
40
|
### Added
|
|
23
41
|
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
grift (2.
|
|
4
|
+
grift (2.1.0)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
@@ -10,53 +10,56 @@ 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
|
+
json (2.6.3)
|
|
19
|
+
minitest (5.16.3)
|
|
18
20
|
minitest-reporters (1.5.0)
|
|
19
21
|
ansi
|
|
20
22
|
builder
|
|
21
23
|
minitest (>= 5.0)
|
|
22
24
|
ruby-progressbar
|
|
23
|
-
overcommit (0.
|
|
25
|
+
overcommit (0.59.1)
|
|
24
26
|
childprocess (>= 0.6.3, < 5)
|
|
25
27
|
iniparse (~> 1.4)
|
|
26
28
|
rexml (~> 3.2)
|
|
27
|
-
parallel (1.
|
|
28
|
-
parser (3.1.
|
|
29
|
+
parallel (1.22.1)
|
|
30
|
+
parser (3.1.3.0)
|
|
29
31
|
ast (~> 2.4.1)
|
|
30
32
|
rainbow (3.1.1)
|
|
31
33
|
rake (13.0.6)
|
|
32
|
-
regexp_parser (2.
|
|
34
|
+
regexp_parser (2.6.1)
|
|
33
35
|
rexml (3.2.5)
|
|
34
|
-
rubocop (1.
|
|
36
|
+
rubocop (1.41.1)
|
|
37
|
+
json (~> 2.3)
|
|
35
38
|
parallel (~> 1.10)
|
|
36
|
-
parser (>= 3.1.
|
|
39
|
+
parser (>= 3.1.2.1)
|
|
37
40
|
rainbow (>= 2.2.2, < 4.0)
|
|
38
41
|
regexp_parser (>= 1.8, < 3.0)
|
|
39
|
-
rexml
|
|
40
|
-
rubocop-ast (>= 1.
|
|
42
|
+
rexml (>= 3.2.5, < 4.0)
|
|
43
|
+
rubocop-ast (>= 1.23.0, < 2.0)
|
|
41
44
|
ruby-progressbar (~> 1.7)
|
|
42
45
|
unicode-display_width (>= 1.4.0, < 3.0)
|
|
43
|
-
rubocop-ast (1.
|
|
46
|
+
rubocop-ast (1.24.0)
|
|
44
47
|
parser (>= 3.1.1.0)
|
|
45
|
-
rubocop-minitest (0.
|
|
48
|
+
rubocop-minitest (0.25.1)
|
|
46
49
|
rubocop (>= 0.90, < 2.0)
|
|
47
|
-
rubocop-packaging (0.5.
|
|
48
|
-
rubocop (>=
|
|
49
|
-
rubocop-performance (1.
|
|
50
|
+
rubocop-packaging (0.5.2)
|
|
51
|
+
rubocop (>= 1.33, < 2.0)
|
|
52
|
+
rubocop-performance (1.15.2)
|
|
50
53
|
rubocop (>= 1.7.0, < 2.0)
|
|
51
54
|
rubocop-ast (>= 0.4.0)
|
|
52
55
|
ruby-progressbar (1.11.0)
|
|
53
|
-
simplecov (0.
|
|
56
|
+
simplecov (0.22.0)
|
|
54
57
|
docile (~> 1.1)
|
|
55
58
|
simplecov-html (~> 0.11)
|
|
56
59
|
simplecov_json_formatter (~> 0.1)
|
|
57
60
|
simplecov-html (0.12.3)
|
|
58
|
-
simplecov_json_formatter (0.1.
|
|
59
|
-
unicode-display_width (2.
|
|
61
|
+
simplecov_json_formatter (0.1.4)
|
|
62
|
+
unicode-display_width (2.3.0)
|
|
60
63
|
|
|
61
64
|
PLATFORMS
|
|
62
65
|
ruby
|
|
@@ -75,4 +78,4 @@ DEPENDENCIES
|
|
|
75
78
|
simplecov (>= 0.21.2)
|
|
76
79
|
|
|
77
80
|
BUNDLED WITH
|
|
78
|
-
2.
|
|
81
|
+
2.2.32
|
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
|
|
|
@@ -86,6 +85,7 @@ my_spy.mock_implementation do |arg1, arg2, **kwargs|
|
|
|
86
85
|
x = do_something(arg1, arg2, kwargs[:arg3], kwargs[:arg4])
|
|
87
86
|
do_something_else(x) # the last line will be returned
|
|
88
87
|
end
|
|
88
|
+
```
|
|
89
89
|
|
|
90
90
|
### Chaining
|
|
91
91
|
|
|
@@ -122,7 +122,7 @@ my_mock.mock.results
|
|
|
122
122
|
|
|
123
123
|
## Requirements
|
|
124
124
|
|
|
125
|
-
Grift supports all Ruby versions >= 2.7 (including 3.
|
|
125
|
+
Grift supports all Ruby versions >= 2.7 (including 3.2).
|
|
126
126
|
|
|
127
127
|
## Development
|
|
128
128
|
|
data/lib/grift/mock_method.rb
CHANGED
|
@@ -134,6 +134,8 @@ module Grift
|
|
|
134
134
|
# @return [self] the mock itself
|
|
135
135
|
#
|
|
136
136
|
def mock_implementation(*)
|
|
137
|
+
raise(Grift::Error, 'Must provide a block for the new implementation') unless block_given?
|
|
138
|
+
|
|
137
139
|
premock_setup
|
|
138
140
|
mock_executions = @mock_executions # required to access inside class instance block
|
|
139
141
|
|
|
@@ -143,7 +145,116 @@ module Grift
|
|
|
143
145
|
|
|
144
146
|
# record the args passed in the call to the method and the result
|
|
145
147
|
mock_executions.store(args: args, result: return_value)
|
|
146
|
-
|
|
148
|
+
return_value
|
|
149
|
+
end
|
|
150
|
+
class_instance.send(@method_access, @method_name)
|
|
151
|
+
|
|
152
|
+
self
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
##
|
|
156
|
+
# Accepts a block and mocks the method to execute that block instead
|
|
157
|
+
# of the original behavior the next time the method is called while mocked.
|
|
158
|
+
# After the method has been called once, it will return to its original
|
|
159
|
+
# behavior. The method will continue to be watched.
|
|
160
|
+
#
|
|
161
|
+
# @see #mock_implementation
|
|
162
|
+
#
|
|
163
|
+
# @example
|
|
164
|
+
# my_mock = Grift.spy_on(String, :downcase).mock_implementation_once do
|
|
165
|
+
# x = 3 + 4
|
|
166
|
+
# x.to_s
|
|
167
|
+
# end
|
|
168
|
+
# ["Banana", "Apple"].map(&:downcase)
|
|
169
|
+
# #=> ["7", "apple"]
|
|
170
|
+
#
|
|
171
|
+
# @return [self] the mock itself
|
|
172
|
+
#
|
|
173
|
+
def mock_implementation_once(*)
|
|
174
|
+
raise(Grift::Error, 'Must provide a block for the new implementation') unless block_given?
|
|
175
|
+
|
|
176
|
+
premock_setup
|
|
177
|
+
|
|
178
|
+
# required to access inside class instance block
|
|
179
|
+
mock_executions = @mock_executions
|
|
180
|
+
clean_mock = lambda do
|
|
181
|
+
unmock_method
|
|
182
|
+
watch_method
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
class_instance.remove_method(@method_name) if !@inherited && method_defined?
|
|
186
|
+
class_instance.define_method @method_name do |*args, **kwargs|
|
|
187
|
+
return_value = yield(*args, **kwargs)
|
|
188
|
+
|
|
189
|
+
# record the args passed in the call to the method and the result
|
|
190
|
+
mock_executions.store(args: args, result: return_value)
|
|
191
|
+
|
|
192
|
+
clean_mock.call
|
|
193
|
+
|
|
194
|
+
return_value
|
|
195
|
+
end
|
|
196
|
+
class_instance.send(@method_access, @method_name)
|
|
197
|
+
|
|
198
|
+
self
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
##
|
|
202
|
+
# Accepts a number +n+ and a block and mocks the method to execute that block
|
|
203
|
+
# instaead of the original behavior the next +n+ times the method is called
|
|
204
|
+
# while mocked. After the method has been called once, it will return to its
|
|
205
|
+
# original behavior. The method will continue to be watched.
|
|
206
|
+
#
|
|
207
|
+
# **IMPORANT:** Calling {#mock_clear} clears the method call history. If it is
|
|
208
|
+
# called before the nth execution of the mocked method, the method will remain
|
|
209
|
+
# mocked for an additonal +n+ calls.
|
|
210
|
+
#
|
|
211
|
+
# @see #mock_implementation
|
|
212
|
+
#
|
|
213
|
+
# @example
|
|
214
|
+
# my_mock = Grift.spy_on(String, :downcase).mock_implementation_n_times(3) do
|
|
215
|
+
# x = 3 + 4
|
|
216
|
+
# x.to_s
|
|
217
|
+
# end
|
|
218
|
+
# ["Banana", "Apple", "Orange", "Guava"].map(&:downcase)
|
|
219
|
+
# #=> ["7", "7", "7", "guava"]
|
|
220
|
+
#
|
|
221
|
+
# @example
|
|
222
|
+
# my_mock = Grift.spy_on(String, :downcase).mock_implementation_n_times(5) do
|
|
223
|
+
# x = 3 + 4
|
|
224
|
+
# x.to_s
|
|
225
|
+
# end
|
|
226
|
+
# ["Banana", "Apple", "Orange", "Guava"].map(&:downcase)
|
|
227
|
+
# #=> ["7", "7", "7", "7"]
|
|
228
|
+
# my_mock.mock_clear # clear mock history before 5th (nth) method call
|
|
229
|
+
# ["Banana", "Apple", "Orange", "Guava"].map(&:downcase)
|
|
230
|
+
# #=> ["7", "7", "7", "7"]
|
|
231
|
+
#
|
|
232
|
+
# @param n [Number] the number of times to mock the implementation
|
|
233
|
+
#
|
|
234
|
+
# @return [self] the mock itself
|
|
235
|
+
#
|
|
236
|
+
def mock_implementation_n_times(n, *)
|
|
237
|
+
raise(Grift::Error, 'Must provide a block for the new implementation') unless block_given?
|
|
238
|
+
|
|
239
|
+
premock_setup
|
|
240
|
+
|
|
241
|
+
# required to access inside class instance block
|
|
242
|
+
mock_executions = @mock_executions
|
|
243
|
+
clean_mock = lambda do
|
|
244
|
+
unmock_method
|
|
245
|
+
watch_method
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
class_instance.remove_method(@method_name) if !@inherited && method_defined?
|
|
249
|
+
class_instance.define_method @method_name do |*args, **kwargs|
|
|
250
|
+
return_value = yield(*args, **kwargs)
|
|
251
|
+
|
|
252
|
+
# record the args passed in the call to the method and the result
|
|
253
|
+
mock_executions.store(args: args, result: return_value)
|
|
254
|
+
|
|
255
|
+
clean_mock.call if mock_executions.count == n
|
|
256
|
+
|
|
257
|
+
return_value
|
|
147
258
|
end
|
|
148
259
|
class_instance.send(@method_access, @method_name)
|
|
149
260
|
|
|
@@ -173,7 +284,144 @@ module Grift
|
|
|
173
284
|
class_instance.define_method @method_name do |*args, **kwargs|
|
|
174
285
|
# record the args passed in the call to the method and the result
|
|
175
286
|
mock_executions.store(args: args, kwargs: kwargs, result: return_value)
|
|
176
|
-
|
|
287
|
+
return_value
|
|
288
|
+
end
|
|
289
|
+
class_instance.send(@method_access, @method_name)
|
|
290
|
+
|
|
291
|
+
self
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
##
|
|
295
|
+
# Accepts a value and mocks the method to return that value once instead
|
|
296
|
+
# of executing its original behavior while mocked. After the method has
|
|
297
|
+
# been called once, it will return to its original behavior. The method
|
|
298
|
+
# will continue to be watched.
|
|
299
|
+
#
|
|
300
|
+
# @example
|
|
301
|
+
# my_mock = Grift.spy_on(String, :upcase).mock_return_value_once("BANANA")
|
|
302
|
+
# ["apple", "apple"].map(&:upcase)
|
|
303
|
+
# #=> ["BANANA", "APPLE"]
|
|
304
|
+
#
|
|
305
|
+
# @param return_value the value to return from the method once
|
|
306
|
+
#
|
|
307
|
+
# @return [self] the mock itself
|
|
308
|
+
#
|
|
309
|
+
def mock_return_value_once(return_value = nil)
|
|
310
|
+
premock_setup
|
|
311
|
+
|
|
312
|
+
# required to access mock inside class instance block
|
|
313
|
+
mock_executions = @mock_executions
|
|
314
|
+
clean_mock = lambda do
|
|
315
|
+
unmock_method
|
|
316
|
+
watch_method
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
class_instance.remove_method(@method_name) if !@inherited && method_defined?
|
|
320
|
+
class_instance.define_method @method_name do |*args, **kwargs|
|
|
321
|
+
# record the args passed in the call to the method and the result
|
|
322
|
+
mock_executions.store(args: args, kwargs: kwargs, result: return_value)
|
|
323
|
+
|
|
324
|
+
clean_mock.call
|
|
325
|
+
|
|
326
|
+
return_value
|
|
327
|
+
end
|
|
328
|
+
class_instance.send(@method_access, @method_name)
|
|
329
|
+
|
|
330
|
+
self
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
##
|
|
334
|
+
# Accepts a value and mocks the method to return that value +n+ times instead
|
|
335
|
+
# of executing its original behavior while mocked. After the method has
|
|
336
|
+
# been called +n+ times, it will return to its original behavior. The method
|
|
337
|
+
# will continue to be watched.
|
|
338
|
+
#
|
|
339
|
+
# **IMPORANT:** Calling {#mock_clear} clears the method call history. If it is
|
|
340
|
+
# called before the nth execution of the mocked method, the method will remain
|
|
341
|
+
# mocked for an additional +n+ calls.
|
|
342
|
+
#
|
|
343
|
+
# @example
|
|
344
|
+
# my_mock = Grift.spy_on(String, :upcase).mock_return_value_n_times(2, "BANANA")
|
|
345
|
+
# ["apple", "apple", "apple"].map(&:upcase)
|
|
346
|
+
# #=> ["BANANA", "BANANA", "APPLE"]
|
|
347
|
+
#
|
|
348
|
+
# @example
|
|
349
|
+
# my_mock = Grift.spy_on(String, :upcase).mock_return_value_n_times(4, "BANANA")
|
|
350
|
+
# ["apple", "apple", "apple"].map(&:upcase)
|
|
351
|
+
# #=> ["BANANA", "BANANA", "BANANA"]
|
|
352
|
+
# my_mock.mock_clear # clear mock history before 4th (nth) method call
|
|
353
|
+
# ["apple", "apple", "apple"].map(&:upcase)
|
|
354
|
+
# #=> ["BANANA", "BANANA", "BANANA"]
|
|
355
|
+
#
|
|
356
|
+
# @param n [Number] the number of times to mock the return value
|
|
357
|
+
# @param return_value the value to return from the method +n+ times
|
|
358
|
+
#
|
|
359
|
+
# @return [self] the mock itself
|
|
360
|
+
#
|
|
361
|
+
def mock_return_value_n_times(n, return_value = nil)
|
|
362
|
+
premock_setup
|
|
363
|
+
|
|
364
|
+
# required to access mock inside class instance block
|
|
365
|
+
mock_executions = @mock_executions
|
|
366
|
+
clean_mock = lambda do
|
|
367
|
+
unmock_method
|
|
368
|
+
watch_method
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
class_instance.remove_method(@method_name) if !@inherited && method_defined?
|
|
372
|
+
class_instance.define_method @method_name do |*args, **kwargs|
|
|
373
|
+
# record the args passed in the call to the method and the result
|
|
374
|
+
mock_executions.store(args: args, kwargs: kwargs, result: return_value)
|
|
375
|
+
|
|
376
|
+
clean_mock.call if mock_executions.count == n
|
|
377
|
+
|
|
378
|
+
return_value
|
|
379
|
+
end
|
|
380
|
+
class_instance.send(@method_access, @method_name)
|
|
381
|
+
|
|
382
|
+
self
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
##
|
|
386
|
+
# Accepts an array of values and mocks the method to return those values
|
|
387
|
+
# in order instead of executing its original behavior while mocked. After
|
|
388
|
+
# the method has been called enough times to return each of the values,
|
|
389
|
+
# it will return to its original behavior. The method continue to be watched.
|
|
390
|
+
#
|
|
391
|
+
# @example
|
|
392
|
+
# mock_values = ["APPLE", "BANANA", "ORANGE"]
|
|
393
|
+
# my_mock = Grift.spy_on(String, :upcase).mock_return_values_in_order(mock_values)
|
|
394
|
+
# ["pineapple", "orange", "guava", "mango", "watermelon"].map(&:upcase)
|
|
395
|
+
# #=> ["APPLE", "BANANA", "ORANGE", "MANGO", "WATERMELON"]
|
|
396
|
+
#
|
|
397
|
+
# @param return_values [Array] the values to return from the method in order
|
|
398
|
+
#
|
|
399
|
+
# @return [self] the mock itself
|
|
400
|
+
#
|
|
401
|
+
def mock_return_values_in_order(return_values)
|
|
402
|
+
unless return_values.is_a?(Array) && !return_values.empty?
|
|
403
|
+
raise(Grift::Error, 'Must provide a non-empty array for the return values')
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
premock_setup
|
|
407
|
+
|
|
408
|
+
# required to access mock inside class instance block
|
|
409
|
+
mock_executions = @mock_executions
|
|
410
|
+
clean_mock = lambda do
|
|
411
|
+
unmock_method
|
|
412
|
+
watch_method
|
|
413
|
+
end
|
|
414
|
+
return_values_internal = return_values.dup
|
|
415
|
+
|
|
416
|
+
class_instance.remove_method(@method_name) if !@inherited && method_defined?
|
|
417
|
+
class_instance.define_method @method_name do |*args, **kwargs|
|
|
418
|
+
# record the args passed in the call to the method and the result
|
|
419
|
+
return_value = return_values_internal.shift
|
|
420
|
+
mock_executions.store(args: args, kwargs: kwargs, result: return_value)
|
|
421
|
+
|
|
422
|
+
clean_mock.call if return_values_internal.empty?
|
|
423
|
+
|
|
424
|
+
return_value
|
|
177
425
|
end
|
|
178
426
|
class_instance.send(@method_access, @method_name)
|
|
179
427
|
|
|
@@ -204,7 +452,7 @@ module Grift
|
|
|
204
452
|
# @return [String] the hash of the class and method
|
|
205
453
|
#
|
|
206
454
|
def self.hash_key(klass, method_name)
|
|
207
|
-
"#{klass}
|
|
455
|
+
"#{klass}##{method_name}"
|
|
208
456
|
end
|
|
209
457
|
|
|
210
458
|
private
|
|
@@ -220,12 +468,12 @@ module Grift
|
|
|
220
468
|
cache_method_name = @cache_method_name
|
|
221
469
|
|
|
222
470
|
class_instance.remove_method(@method_name) if !@inherited && method_defined?
|
|
223
|
-
class_instance.define_method @method_name do |*args, **kwargs|
|
|
224
|
-
return_value = send(cache_method_name, *args, **kwargs)
|
|
471
|
+
class_instance.define_method @method_name do |*args, **kwargs, &block|
|
|
472
|
+
return_value = send(cache_method_name, *args, **kwargs, &block)
|
|
225
473
|
|
|
226
474
|
# record the args passed in the call to the method and the result
|
|
227
475
|
mock_executions.store(args: args, kwargs: kwargs, result: return_value)
|
|
228
|
-
|
|
476
|
+
return_value
|
|
229
477
|
end
|
|
230
478
|
class_instance.send(@method_access, @method_name)
|
|
231
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.
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Clark Brown
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-
|
|
11
|
+
date: 2022-12-27 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:
|
|
@@ -69,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
69
69
|
- !ruby/object:Gem::Version
|
|
70
70
|
version: '0'
|
|
71
71
|
requirements: []
|
|
72
|
-
rubygems_version: 3.
|
|
72
|
+
rubygems_version: 3.3.26
|
|
73
73
|
signing_key:
|
|
74
74
|
specification_version: 4
|
|
75
75
|
summary: Mocking and spying in MiniTest
|