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.
@@ -37,11 +37,11 @@ class FlexMock
37
37
  @sym = sym
38
38
  @location = location
39
39
  @expected_args = nil
40
- @expected_kw_args = nil
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
- result << ".with(#{FlexMock.format_args(@expected_args)})" if @expected_args
68
- result << ".with_kw_args(#{FlexMock.format_kw_args(@expected_kw_args)})" if @expected_kw_args
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(*args, &block)
98
+ def verify_call(args, kw, block)
98
99
  validate_eligible
99
100
  validate_order
100
- enhanced_args =
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(args, block)
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 { |*a| @return_value }
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(args, block)
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 with_kw_args(matcher)
245
- @expected_kw_args =
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 with_any_kw_args
257
- @expected_kw_args = FlexMock.any
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
- required_arguments: 0, optional_arguments: 0, splat: false,
264
- required_keyword_arguments: [], optional_keyword_arguments: [], keyword_splat: false)
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
- self,
267
- required_arguments: required_arguments,
268
- optional_arguments: optional_arguments,
269
- splat: splat,
270
- required_keyword_arguments: required_keyword_arguments,
271
- optional_keyword_arguments: optional_keyword_arguments,
272
- keyword_splat: keyword_splat)
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 = SignatureValidator.from_instance_method(self, instance_method)
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, &orig_block|
395
+ and_return { |*args, **kw|
415
396
  begin
416
- if @expected_block.nil? && !orig_block
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 = nil, call_record=nil)
39
- find_args = args.dup
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(*args, &block)
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(*args) # :nodoc:
57
+ def find_expectation(args, kw, block) # :nodoc:
60
58
  if @expectations.empty?
61
- find_expectation_in(@defaults, *args)
59
+ find_expectation_in(@defaults, args, kw, block)
62
60
  else
63
- find_expectation_in(@expectations, *args)
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, *args)
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.__send__(sym, *args, &block)
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
- flexmock_invoke_original(m, args, block)
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 = @obj.method(m)
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 flexmock_define_expectation(location, *args)
204
- EXP_BUILDER.parse_should_args(self, args) do |method_name|
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
- ex.with_signature_matching(existing_method)
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
- # Workaround kw arg support for ruby < 2.7
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, nil)
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, block)
349
+ def flexmock_invoke_original(method, args, kw)
333
350
  if (original_method = find_original_method(method))
334
- original_method.call(*args, &block)
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
- bool = spy.flexmock_received?(method_name, args, options)
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