flexmock 2.4.5 → 3.0.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/test.yml +5 -1
- data/README.md +60 -6
- data/flexmock.gemspec +1 -1
- data/lib/flexmock/argument_matchers.rb +3 -48
- data/lib/flexmock/argument_matching.rb +31 -1
- data/lib/flexmock/argument_types.rb +0 -4
- data/lib/flexmock/call_record.rb +10 -5
- data/lib/flexmock/call_validator.rb +2 -2
- data/lib/flexmock/composite_expectation.rb +5 -6
- data/lib/flexmock/core.rb +21 -18
- data/lib/flexmock/core_class_methods.rb +28 -21
- data/lib/flexmock/expectation.rb +68 -93
- data/lib/flexmock/expectation_builder.rb +9 -3
- data/lib/flexmock/expectation_director.rb +10 -12
- data/lib/flexmock/expectation_recorder.rb +4 -4
- data/lib/flexmock/explicit_needed.rb +2 -2
- data/lib/flexmock/partial_mock.rb +53 -32
- data/lib/flexmock/spy_describers.rb +9 -9
- data/lib/flexmock/test_unit_assert_spy_called.rb +15 -8
- data/lib/flexmock/validators.rb +10 -57
- data/lib/flexmock/version.rb +1 -1
- metadata +7 -7
data/lib/flexmock/expectation.rb
CHANGED
@@ -37,11 +37,11 @@ class FlexMock
|
|
37
37
|
@sym = sym
|
38
38
|
@location = location
|
39
39
|
@expected_args = nil
|
40
|
-
@
|
41
|
-
@expected_block = nil
|
40
|
+
@expected_kw = nil
|
42
41
|
@count_validators = []
|
43
42
|
@signature_validator = SignatureValidator.new(self)
|
44
43
|
@count_validator_class = ExactCountValidator
|
44
|
+
@with_block = nil
|
45
45
|
@actual_count = 0
|
46
46
|
@return_value = nil
|
47
47
|
@return_queue = []
|
@@ -52,7 +52,7 @@ class FlexMock
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def to_s
|
55
|
-
FlexMock.format_call(@sym, @expected_args)
|
55
|
+
FlexMock.format_call(@sym, @expected_args, @expected_kw)
|
56
56
|
end
|
57
57
|
|
58
58
|
# Return a description of the matching features of the
|
@@ -64,8 +64,9 @@ class FlexMock
|
|
64
64
|
#
|
65
65
|
def description
|
66
66
|
result = ["should_receive(#{@sym.inspect})"]
|
67
|
-
|
68
|
-
|
67
|
+
if @expected_args || @expected_kw
|
68
|
+
result << ".with(#{FlexMock.format_args(@expected_args, @expected_kw)})"
|
69
|
+
end
|
69
70
|
@count_validators.each do |validator|
|
70
71
|
result << validator.describe
|
71
72
|
end
|
@@ -86,63 +87,49 @@ class FlexMock
|
|
86
87
|
FlexMock.framework_adapter.check(e.message) { false }
|
87
88
|
end
|
88
89
|
|
89
|
-
def validate_signature(args)
|
90
|
-
@signature_validator.validate(args)
|
90
|
+
def validate_signature(args, kw, block)
|
91
|
+
@signature_validator.validate(args, kw, block)
|
91
92
|
rescue SignatureValidator::ValidationFailed => e
|
92
93
|
FlexMock.framework_adapter.check(e.message) { false }
|
93
94
|
end
|
94
95
|
|
95
96
|
# Verify the current call with the given arguments matches the
|
96
97
|
# expectations recorded in this object.
|
97
|
-
def verify_call(
|
98
|
+
def verify_call(args, kw, block)
|
98
99
|
validate_eligible
|
99
100
|
validate_order
|
100
|
-
|
101
|
-
if block
|
102
|
-
args + [block]
|
103
|
-
else
|
104
|
-
args
|
105
|
-
end
|
106
|
-
|
107
|
-
validate_signature(enhanced_args)
|
101
|
+
validate_signature(args, kw, block)
|
108
102
|
@actual_count += 1
|
109
|
-
perform_yielding(
|
110
|
-
return_value(args, block)
|
103
|
+
perform_yielding(block)
|
104
|
+
return_value(args, kw, block)
|
111
105
|
end
|
112
106
|
|
113
107
|
# Public return value (odd name to avoid accidental use as a
|
114
108
|
# constraint).
|
115
|
-
def _return_value(args, block) # :nodoc:
|
116
|
-
return_value(args, block)
|
109
|
+
def _return_value(args, kw, block) # :nodoc:
|
110
|
+
return_value(args, kw, block)
|
117
111
|
end
|
118
112
|
|
119
113
|
# Find the return value for this expectation. (private version)
|
120
|
-
def return_value(args, block)
|
114
|
+
def return_value(args, kw, block)
|
121
115
|
case @return_queue.size
|
122
116
|
when 0
|
123
|
-
ret_block = lambda {
|
117
|
+
ret_block = lambda { |*, **| @return_value }
|
124
118
|
when 1
|
125
119
|
ret_block = @return_queue.first
|
126
120
|
else
|
127
121
|
ret_block = @return_queue.shift
|
128
122
|
end
|
129
|
-
|
130
|
-
if @expected_block
|
131
|
-
ret_block.call(*args, &block)
|
132
|
-
elsif block && @expected_block.nil?
|
133
|
-
ret_block.call(*args, block)
|
134
|
-
else
|
135
|
-
ret_block.call(*args)
|
136
|
-
end
|
123
|
+
ret_block.call(*args, **kw, &block)
|
137
124
|
end
|
138
125
|
private :return_value
|
139
126
|
|
140
127
|
# Yield stored values to any blocks given.
|
141
|
-
def perform_yielding(
|
128
|
+
def perform_yielding(block)
|
142
129
|
@return_value = nil
|
143
130
|
unless @yield_queue.empty?
|
144
131
|
values = (@yield_queue.size == 1) ? @yield_queue.first : @yield_queue.shift
|
145
|
-
if block
|
132
|
+
if block && block.respond_to?(:call)
|
146
133
|
values.each do |v|
|
147
134
|
@return_value = block.call(*v)
|
148
135
|
end
|
@@ -186,44 +173,14 @@ class FlexMock
|
|
186
173
|
|
187
174
|
# Does the argument list match this expectation's argument
|
188
175
|
# specification.
|
189
|
-
def match_args(args)
|
190
|
-
expected_args
|
191
|
-
if @expected_kw_args
|
192
|
-
if proc_matcher?(@expected_args&.last) && @expected_block.nil?
|
193
|
-
@expected_args[0..-2] + [@expected_kw_args, @expected_args[-1]]
|
194
|
-
else
|
195
|
-
(@expected_args || []) + [@expected_kw_args]
|
196
|
-
end
|
197
|
-
else
|
198
|
-
@expected_args
|
199
|
-
end
|
200
|
-
|
201
|
-
if @expected_block
|
202
|
-
expected_args = (expected_args || []) + [@expected_block]
|
203
|
-
end
|
204
|
-
|
205
|
-
ArgumentMatching.all_match?(expected_args, args)
|
206
|
-
end
|
207
|
-
|
208
|
-
def proc_matcher?(obj)
|
209
|
-
obj == Proc || obj == OPTIONAL_PROC_MATCHER
|
210
|
-
end
|
211
|
-
|
212
|
-
def with_optional_block
|
213
|
-
@expected_block = OPTIONAL_PROC_MATCHER
|
214
|
-
end
|
215
|
-
|
216
|
-
def with_block
|
217
|
-
@expected_block = Proc
|
218
|
-
end
|
219
|
-
|
220
|
-
def with_no_block
|
221
|
-
@expected_block = false
|
176
|
+
def match_args(args, kw, block)
|
177
|
+
ArgumentMatching.all_match?(@expected_args, @expected_kw, @expected_block, args, kw, block)
|
222
178
|
end
|
223
179
|
|
224
180
|
# Declare that the method should expect the given argument list.
|
225
|
-
def with(*args)
|
181
|
+
def with(*args, **kw)
|
226
182
|
@expected_args = args
|
183
|
+
@expected_kw = kw
|
227
184
|
self
|
228
185
|
end
|
229
186
|
|
@@ -236,47 +193,71 @@ class FlexMock
|
|
236
193
|
# arguments of any type.
|
237
194
|
def with_any_args
|
238
195
|
@expected_args = nil
|
196
|
+
@expected_kw = nil
|
239
197
|
self
|
240
198
|
end
|
241
199
|
|
242
200
|
# Declare that the method can be called with any number of
|
243
201
|
# arguments of any type.
|
244
|
-
def
|
245
|
-
@
|
246
|
-
if matcher.kind_of?(Hash)
|
247
|
-
KwArgsMatcher.new(matcher)
|
248
|
-
else
|
249
|
-
matcher
|
250
|
-
end
|
202
|
+
def with_any_kw_args
|
203
|
+
@expected_kw = nil
|
251
204
|
self
|
252
205
|
end
|
253
206
|
|
254
207
|
# Declare that the method can be called with any number of
|
255
208
|
# arguments of any type.
|
256
|
-
def
|
257
|
-
@
|
209
|
+
def with_any_positional_args
|
210
|
+
@expected_args = nil
|
211
|
+
self
|
212
|
+
end
|
213
|
+
|
214
|
+
# Declare that the method should be called with the given
|
215
|
+
# keyword arguments
|
216
|
+
def with_kw_args(kw)
|
217
|
+
@expected_kw = kw
|
218
|
+
self
|
219
|
+
end
|
220
|
+
|
221
|
+
# Declare that the call should have a block
|
222
|
+
def with_block
|
223
|
+
@expected_block = true
|
224
|
+
self
|
225
|
+
end
|
226
|
+
|
227
|
+
# Declare that the call should have a block
|
228
|
+
def with_no_block
|
229
|
+
@expected_block = false
|
230
|
+
self
|
231
|
+
end
|
232
|
+
|
233
|
+
def with_optional_block
|
234
|
+
@expected_block = nil
|
258
235
|
self
|
259
236
|
end
|
260
237
|
|
261
238
|
# Validate general parameters on the call signature
|
262
239
|
def with_signature(
|
263
|
-
|
264
|
-
|
240
|
+
required_arguments: 0, optional_arguments: 0, splat: false,
|
241
|
+
required_keyword_arguments: [], optional_keyword_arguments: [],
|
242
|
+
keyword_splat: false
|
243
|
+
)
|
265
244
|
@signature_validator = SignatureValidator.new(
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
245
|
+
self,
|
246
|
+
required_arguments: required_arguments,
|
247
|
+
optional_arguments: optional_arguments,
|
248
|
+
splat: splat,
|
249
|
+
required_keyword_arguments: required_keyword_arguments,
|
250
|
+
optional_keyword_arguments: optional_keyword_arguments,
|
251
|
+
keyword_splat: keyword_splat
|
252
|
+
)
|
273
253
|
self
|
274
254
|
end
|
275
255
|
|
276
256
|
# Validate that the passed arguments match the method signature from the
|
277
257
|
# given instance method
|
278
258
|
def with_signature_matching(instance_method)
|
279
|
-
@signature_validator =
|
259
|
+
@signature_validator =
|
260
|
+
SignatureValidator.from_instance_method(self, instance_method)
|
280
261
|
self
|
281
262
|
end
|
282
263
|
|
@@ -411,15 +392,9 @@ class FlexMock
|
|
411
392
|
|
412
393
|
def pass_thru(&block)
|
413
394
|
block ||= lambda { |value| value }
|
414
|
-
and_return { |*args,
|
395
|
+
and_return { |*args, **kw|
|
415
396
|
begin
|
416
|
-
|
417
|
-
if Proc === args.last
|
418
|
-
orig_block = args.last
|
419
|
-
args = args[0..-2]
|
420
|
-
end
|
421
|
-
end
|
422
|
-
block.call(@mock.flexmock_invoke_original(@sym, args, orig_block))
|
397
|
+
block.call(@mock.flexmock_invoke_original(@sym, args, kw))
|
423
398
|
rescue NoMethodError => e
|
424
399
|
if e.name == @sym
|
425
400
|
raise e, "#{e.message} while performing #pass_thru in expectation object #{self}"
|
@@ -22,12 +22,12 @@ class FlexMock
|
|
22
22
|
# hashes, and identifies the method names specified by each. As each
|
23
23
|
# method name is identified, create a mock expectation for it using the
|
24
24
|
# supplied block.
|
25
|
-
def parse_should_args(mock, args, &block) # :nodoc:
|
25
|
+
def parse_should_args(mock, args, kw, &block) # :nodoc:
|
26
26
|
result = CompositeExpectation.new
|
27
27
|
args.each do |arg|
|
28
28
|
case arg
|
29
29
|
when Hash
|
30
|
-
arg.each do |k,v|
|
30
|
+
arg.each do |k, v|
|
31
31
|
exp = create_expectation(mock, k, &block).and_return(v)
|
32
32
|
result.add(exp)
|
33
33
|
end
|
@@ -35,6 +35,12 @@ class FlexMock
|
|
35
35
|
result.add(create_expectation(mock, arg, &block))
|
36
36
|
end
|
37
37
|
end
|
38
|
+
|
39
|
+
kw.each do |k, v|
|
40
|
+
exp = create_expectation(mock, k, &block).and_return(v)
|
41
|
+
result.add(exp)
|
42
|
+
end
|
43
|
+
|
38
44
|
result
|
39
45
|
end
|
40
46
|
|
@@ -86,7 +92,7 @@ class FlexMock
|
|
86
92
|
names.each do |name|
|
87
93
|
exp = mock.flexmock_find_expectation(name)
|
88
94
|
if exp
|
89
|
-
next_mock = exp._return_value([], nil)
|
95
|
+
next_mock = exp._return_value([], {}, nil)
|
90
96
|
check_proper_mock(next_mock, name)
|
91
97
|
else
|
92
98
|
next_mock = container.flexmock("demeter_#{name}")
|
@@ -35,18 +35,16 @@ class FlexMock
|
|
35
35
|
# but at least we will get a good failure message). Finally,
|
36
36
|
# check for expectations that don't have any argument matching
|
37
37
|
# criteria.
|
38
|
-
def call(args, block
|
39
|
-
|
40
|
-
find_args << block if block
|
41
|
-
exp = find_expectation(*find_args)
|
38
|
+
def call(args, kw, block, call_record=nil)
|
39
|
+
exp = find_expectation(args, kw, block)
|
42
40
|
call_record.expectation = exp if call_record
|
43
41
|
FlexMock.check(
|
44
42
|
proc { "no matching handler found for " +
|
45
|
-
FlexMock.format_call(@sym, args) +
|
43
|
+
FlexMock.format_call(@sym, args, kw) +
|
46
44
|
"\nDefined expectations:\n " +
|
47
45
|
@expectations.map(&:description).join("\n ") }
|
48
46
|
) { !exp.nil? }
|
49
|
-
returned_value = exp.verify_call(
|
47
|
+
returned_value = exp.verify_call(args, kw, block)
|
50
48
|
returned_value
|
51
49
|
end
|
52
50
|
|
@@ -56,11 +54,11 @@ class FlexMock
|
|
56
54
|
end
|
57
55
|
|
58
56
|
# Find an expectation matching the given arguments.
|
59
|
-
def find_expectation(
|
57
|
+
def find_expectation(args, kw, block) # :nodoc:
|
60
58
|
if @expectations.empty?
|
61
|
-
find_expectation_in(@defaults,
|
59
|
+
find_expectation_in(@defaults, args, kw, block)
|
62
60
|
else
|
63
|
-
find_expectation_in(@expectations,
|
61
|
+
find_expectation_in(@expectations, args, kw, block)
|
64
62
|
end
|
65
63
|
end
|
66
64
|
|
@@ -86,9 +84,9 @@ class FlexMock
|
|
86
84
|
|
87
85
|
private
|
88
86
|
|
89
|
-
def find_expectation_in(expectations,
|
90
|
-
expectations.find { |e| e.match_args(args) && e.eligible? } ||
|
91
|
-
expectations.find { |e| e.match_args(args) }
|
87
|
+
def find_expectation_in(expectations, args, kw, block)
|
88
|
+
expectations.find { |e| e.match_args(args, kw, block) && e.eligible? } ||
|
89
|
+
expectations.find { |e| e.match_args(args, kw, block) }
|
92
90
|
end
|
93
91
|
end
|
94
92
|
|
@@ -23,8 +23,8 @@ class FlexMock
|
|
23
23
|
end
|
24
24
|
|
25
25
|
# Save any incoming messages to be played back later.
|
26
|
-
def method_missing(sym, *args, &block)
|
27
|
-
@expectations << [sym, args, block]
|
26
|
+
def method_missing(sym, *args, **kw, &block)
|
27
|
+
@expectations << [sym, args, kw, block]
|
28
28
|
self
|
29
29
|
end
|
30
30
|
|
@@ -33,8 +33,8 @@ class FlexMock
|
|
33
33
|
# call).
|
34
34
|
def apply(mock)
|
35
35
|
obj = mock
|
36
|
-
@expectations.each do |sym, args, block|
|
37
|
-
obj = obj.
|
36
|
+
@expectations.each do |sym, args, kw, block|
|
37
|
+
obj = obj.send(sym, *args, **kw, &block)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -31,9 +31,9 @@ class FlexMock
|
|
31
31
|
|
32
32
|
WHITELIST = [:with_signature_matching]
|
33
33
|
|
34
|
-
def method_missing(sym, *args, &block)
|
34
|
+
def method_missing(sym, *args, **kw, &block)
|
35
35
|
if explicit? || WHITELIST.include?(sym)
|
36
|
-
@expectation.send(sym, *args, &block)
|
36
|
+
@expectation.send(sym, *args, **kw, &block)
|
37
37
|
else
|
38
38
|
fail NoMethodError, "Cannot stub methods not defined by the base class\n" +
|
39
39
|
" Method: #{@method_name}\n" +
|
@@ -150,8 +150,8 @@ class FlexMock
|
|
150
150
|
# to the result.
|
151
151
|
#
|
152
152
|
# See Expectation for a list of declarators that can be used.
|
153
|
-
def should_receive(*args)
|
154
|
-
flexmock_define_expectation(caller, *args)
|
153
|
+
def should_receive(*args, **kw)
|
154
|
+
flexmock_define_expectation(caller, *args, **kw)
|
155
155
|
end
|
156
156
|
|
157
157
|
def should_expect(*args)
|
@@ -161,13 +161,22 @@ class FlexMock
|
|
161
161
|
# Invoke the original of a mocked method
|
162
162
|
#
|
163
163
|
# Usually called in a #and_return statement
|
164
|
-
def invoke_original(m, *args, &block)
|
165
|
-
|
164
|
+
def invoke_original(m, *args, **kw, &block)
|
165
|
+
if block
|
166
|
+
args << block
|
167
|
+
end
|
168
|
+
flexmock_invoke_original(m, args, kw)
|
166
169
|
end
|
167
170
|
|
168
171
|
# Whether the given method's original definition has been stored
|
169
172
|
def find_original_method(m)
|
170
|
-
it =
|
173
|
+
it =
|
174
|
+
if m.respond_to?(:to_str) || m.respond_to?(:to_sym)
|
175
|
+
@obj.method(m)
|
176
|
+
else
|
177
|
+
m
|
178
|
+
end
|
179
|
+
|
171
180
|
while it && (it.owner != @proxy_definition_module)
|
172
181
|
it = it.super_method
|
173
182
|
end
|
@@ -200,15 +209,24 @@ class FlexMock
|
|
200
209
|
@proxy_definition_module.method_defined?(m)
|
201
210
|
end
|
202
211
|
|
203
|
-
def
|
204
|
-
|
212
|
+
def flexmock_plain_new_method?(m)
|
213
|
+
m.name == :new && m.owner == Class
|
214
|
+
end
|
215
|
+
|
216
|
+
def flexmock_define_expectation(location, *args, **kw)
|
217
|
+
EXP_BUILDER.parse_should_args(self, args, kw) do |method_name|
|
205
218
|
if !has_proxied_method?(method_name)
|
206
219
|
define_proxy_method(method_name)
|
207
220
|
end
|
208
221
|
ex = @mock.flexmock_define_expectation(location, method_name)
|
209
222
|
if FlexMock.partials_verify_signatures
|
210
223
|
if (existing_method = find_original_method(method_name))
|
211
|
-
|
224
|
+
if flexmock_plain_new_method?(existing_method)
|
225
|
+
# Look for the signature of `initialize` instead
|
226
|
+
ex.with_signature_matching(@obj.instance_method(:initialize))
|
227
|
+
else
|
228
|
+
ex.with_signature_matching(existing_method)
|
229
|
+
end
|
212
230
|
end
|
213
231
|
end
|
214
232
|
ex.mock = self
|
@@ -216,17 +234,17 @@ class FlexMock
|
|
216
234
|
end
|
217
235
|
end
|
218
236
|
|
219
|
-
def flexmock_find_expectation(*args)
|
220
|
-
@mock.flexmock_find_expectation(*args)
|
237
|
+
def flexmock_find_expectation(*args, **kw, &block)
|
238
|
+
@mock.flexmock_find_expectation(*args, **kw, &block)
|
221
239
|
end
|
222
240
|
|
223
241
|
def add_mock_method(method_name)
|
224
242
|
proxy_module_eval do
|
225
|
-
define_method(method_name) { |*args, &block|
|
243
|
+
define_method(method_name) { |*args, **kw, &block|
|
226
244
|
proxy = __flexmock_proxy or
|
227
245
|
fail "Missing FlexMock proxy " +
|
228
246
|
"(for method_name=#{method_name.inspect}, self=\#{self})"
|
229
|
-
proxy.send(method_name, *args, &block)
|
247
|
+
proxy.send(method_name, *args, **kw, &block)
|
230
248
|
}
|
231
249
|
end
|
232
250
|
end
|
@@ -262,9 +280,9 @@ class FlexMock
|
|
262
280
|
end
|
263
281
|
|
264
282
|
allocators.each do |allocate_method|
|
265
|
-
flexmock_define_expectation(location, allocate_method).and_return { |*args|
|
283
|
+
flexmock_define_expectation(location, allocate_method).and_return { |*args, **kw|
|
266
284
|
create_new_mocked_object(
|
267
|
-
allocate_method, args, expectation_recorder, block)
|
285
|
+
allocate_method, args, kw, expectation_recorder, block)
|
268
286
|
}
|
269
287
|
end
|
270
288
|
expectation_recorder
|
@@ -276,7 +294,7 @@ class FlexMock
|
|
276
294
|
expectation_blocks = @initialize_expectation_blocks = Array.new
|
277
295
|
expectation_recorders = @initialize_expectation_recorders = Array.new
|
278
296
|
@initialize_override = Module.new do
|
279
|
-
define_method :initialize do |*args, &block|
|
297
|
+
define_method :initialize do |*args, **kw, &block|
|
280
298
|
if self.class.respond_to?(:__flexmock_proxy) && (mock = self.class.__flexmock_proxy)
|
281
299
|
container = mock.flexmock_container
|
282
300
|
mock = container.flexmock(self)
|
@@ -287,8 +305,7 @@ class FlexMock
|
|
287
305
|
r.apply(mock)
|
288
306
|
end
|
289
307
|
end
|
290
|
-
|
291
|
-
super(*args, &block)
|
308
|
+
super(*args, **kw, &block)
|
292
309
|
end
|
293
310
|
end
|
294
311
|
override = @initialize_override
|
@@ -318,8 +335,8 @@ class FlexMock
|
|
318
335
|
# (2) Pass to the block for custom configuration.
|
319
336
|
# (3) Apply any recorded expecations
|
320
337
|
#
|
321
|
-
def create_new_mocked_object(allocate_method, args, recorder, block)
|
322
|
-
new_obj = flexmock_invoke_original(allocate_method, args,
|
338
|
+
def create_new_mocked_object(allocate_method, args, kw, recorder, block)
|
339
|
+
new_obj = flexmock_invoke_original(allocate_method, args, kw)
|
323
340
|
mock = flexmock_container.flexmock(new_obj)
|
324
341
|
block.call(mock) unless block.nil?
|
325
342
|
recorder.apply(mock)
|
@@ -329,11 +346,15 @@ class FlexMock
|
|
329
346
|
|
330
347
|
# Invoke the original definition of method on the object supported by
|
331
348
|
# the stub.
|
332
|
-
def flexmock_invoke_original(method, args,
|
349
|
+
def flexmock_invoke_original(method, args, kw)
|
333
350
|
if (original_method = find_original_method(method))
|
334
|
-
|
351
|
+
if Proc === args.last
|
352
|
+
block = args.last
|
353
|
+
args = args[0..-2]
|
354
|
+
end
|
355
|
+
original_method.call(*args, **kw, &block)
|
335
356
|
else
|
336
|
-
@obj.__send__(:method_missing, method, *args, &block)
|
357
|
+
@obj.__send__(:method_missing, method, *args, **kw, &block)
|
337
358
|
end
|
338
359
|
end
|
339
360
|
|
@@ -367,8 +388,8 @@ class FlexMock
|
|
367
388
|
end
|
368
389
|
|
369
390
|
# Forward to the mock
|
370
|
-
def flexmock_received?(*args)
|
371
|
-
@mock.flexmock_received?(*args)
|
391
|
+
def flexmock_received?(*args, **kw)
|
392
|
+
@mock.flexmock_received?(*args, **kw)
|
372
393
|
end
|
373
394
|
|
374
395
|
# Forward to the mock
|
@@ -400,15 +421,15 @@ class FlexMock
|
|
400
421
|
|
401
422
|
# Evaluate a block (or string) in the context of the singleton
|
402
423
|
# class of the target partial object.
|
403
|
-
def target_class_eval(*args, &block)
|
404
|
-
target_singleton_class.class_eval(*args, &block)
|
424
|
+
def target_class_eval(*args, **kw, &block)
|
425
|
+
target_singleton_class.class_eval(*args, **kw, &block)
|
405
426
|
end
|
406
427
|
|
407
428
|
class ProxyDefinitionModule < Module
|
408
429
|
end
|
409
430
|
|
410
431
|
# Evaluate a block into the module we use to define the proxy methods
|
411
|
-
def proxy_module_eval(*args, &block)
|
432
|
+
def proxy_module_eval(*args, **kw, &block)
|
412
433
|
if !@proxy_definition_module
|
413
434
|
obj = @obj
|
414
435
|
@proxy_definition_module = m = ProxyDefinitionModule.new do
|
@@ -420,7 +441,7 @@ class FlexMock
|
|
420
441
|
end
|
421
442
|
target_class_eval { prepend m }
|
422
443
|
end
|
423
|
-
@proxy_definition_module.class_eval(*args, &block)
|
444
|
+
@proxy_definition_module.class_eval(*args, **kw, &block)
|
424
445
|
end
|
425
446
|
|
426
447
|
# Hide the existing method definition with a singleton defintion
|
@@ -439,15 +460,15 @@ class FlexMock
|
|
439
460
|
def define_proxy_method(method_name)
|
440
461
|
if method_name =~ /=$/
|
441
462
|
proxy_module_eval do
|
442
|
-
define_method(method_name) do |*args, &block|
|
443
|
-
__flexmock_proxy.mock.__send__(method_name, *args, &block)
|
463
|
+
define_method(method_name) do |*args, **kw, &block|
|
464
|
+
__flexmock_proxy.mock.__send__(method_name, *args, **kw, &block)
|
444
465
|
end
|
445
466
|
end
|
446
467
|
else
|
447
468
|
proxy_module_eval <<-EOD
|
448
|
-
def #{method_name}(*args, &block)
|
469
|
+
def #{method_name}(*args, **kw, &block)
|
449
470
|
FlexMock.verify_mocking_allowed!
|
450
|
-
__flexmock_proxy.mock.#{method_name}(*args, &block)
|
471
|
+
__flexmock_proxy.mock.#{method_name}(*args, **kw, &block)
|
451
472
|
end
|
452
473
|
EOD
|
453
474
|
end
|
@@ -1,25 +1,25 @@
|
|
1
1
|
class FlexMock
|
2
2
|
|
3
3
|
module SpyDescribers
|
4
|
-
def spy_description(spy, sym, args, options)
|
4
|
+
def spy_description(spy, sym, args, kw, options)
|
5
5
|
result = "have received "
|
6
|
-
result << FlexMock.format_call(sym, args)
|
6
|
+
result << FlexMock.format_call(sym, args, kw)
|
7
7
|
result << times_description(options[:times])
|
8
8
|
result << block_description(options[:with_block])
|
9
9
|
result
|
10
10
|
end
|
11
11
|
|
12
|
-
def describe_spy_expectation(spy, sym, args, options={})
|
13
|
-
describe_spy(spy, sym, args, options)
|
12
|
+
def describe_spy_expectation(spy, sym, args, kw, options={})
|
13
|
+
describe_spy(spy, sym, args, kw, options)
|
14
14
|
end
|
15
15
|
|
16
|
-
def describe_spy_negative_expectation(spy, sym, args, options={})
|
17
|
-
describe_spy(spy, sym, args, options, " NOT")
|
16
|
+
def describe_spy_negative_expectation(spy, sym, args, kw, options={})
|
17
|
+
describe_spy(spy, sym, args, kw, options, " NOT")
|
18
18
|
end
|
19
19
|
|
20
|
-
def describe_spy(spy, sym, args, options, not_clause="")
|
20
|
+
def describe_spy(spy, sym, args, kw, options, not_clause="")
|
21
21
|
result = "expected "
|
22
|
-
result << FlexMock.format_call(sym, args)
|
22
|
+
result << FlexMock.format_call(sym, args, kw)
|
23
23
|
result << " to#{not_clause} be received by " << spy.inspect
|
24
24
|
result << times_description(options[:times])
|
25
25
|
result << block_description(options[:with_block])
|
@@ -44,7 +44,7 @@ class FlexMock
|
|
44
44
|
def append_call_record(result, call_record)
|
45
45
|
result <<
|
46
46
|
" " <<
|
47
|
-
FlexMock.format_call(call_record.method_name, call_record.args)
|
47
|
+
FlexMock.format_call(call_record.method_name, call_record.args, call_record.kw)
|
48
48
|
if call_record.expectation
|
49
49
|
result <<
|
50
50
|
" matched by " <<
|
@@ -4,29 +4,36 @@ class FlexMock
|
|
4
4
|
module TestUnitAssertions
|
5
5
|
include FlexMock::SpyDescribers
|
6
6
|
|
7
|
-
def assert_spy_called(spy, method_name, *args)
|
8
|
-
_assert_spy_called(false, spy, method_name, *args)
|
7
|
+
def assert_spy_called(spy, method_name, *args, **kw)
|
8
|
+
_assert_spy_called(false, spy, method_name, *args, **kw)
|
9
9
|
end
|
10
10
|
|
11
|
-
def assert_spy_not_called(spy, method_name, *args)
|
12
|
-
_assert_spy_called(true, spy, method_name, *args)
|
11
|
+
def assert_spy_not_called(spy, method_name, *args, **kw)
|
12
|
+
_assert_spy_called(true, spy, method_name, *args, **kw)
|
13
13
|
end
|
14
14
|
|
15
15
|
private
|
16
16
|
|
17
|
-
def _assert_spy_called(negative, spy, method_name, *args)
|
17
|
+
def _assert_spy_called(negative, spy, method_name, *args, **kw)
|
18
18
|
options = {}
|
19
19
|
if method_name.is_a?(Hash)
|
20
20
|
options = method_name
|
21
21
|
method_name = args.shift
|
22
22
|
end
|
23
|
+
|
24
|
+
# Prior to ruby3, kw args would be matched in *args
|
25
|
+
# thus, expecting any args (:_) implied also expecting
|
26
|
+
# any kw args.
|
27
|
+
kw = :_ if args == [:_]
|
28
|
+
|
23
29
|
args = nil if args == [:_]
|
24
|
-
|
30
|
+
kw = nil if kw == :_
|
31
|
+
bool = spy.flexmock_received?(method_name, args, kw, options)
|
25
32
|
if negative
|
26
33
|
bool = !bool
|
27
|
-
message = describe_spy_negative_expectation(spy, method_name, args, options)
|
34
|
+
message = describe_spy_negative_expectation(spy, method_name, args, kw, options)
|
28
35
|
else
|
29
|
-
message = describe_spy_expectation(spy, method_name, args, options)
|
36
|
+
message = describe_spy_expectation(spy, method_name, args, kw, options)
|
30
37
|
end
|
31
38
|
assert bool, message
|
32
39
|
end
|