0
# Matchers
1
2
Sophisticated argument matching system with built-in matchers for equality, comparison, type checking, capturing, and logical operations to create flexible and powerful mock interactions.
3
4
## Capabilities
5
6
### Basic Matchers
7
8
Fundamental argument matching functions for common scenarios.
9
10
```kotlin { .api }
11
/**
12
* Matches any argument of the specified type
13
*/
14
fun <T> any(): T
15
16
/**
17
* Matches any nullable argument
18
*/
19
fun <T> anyNullable(): T?
20
21
/**
22
* Matches arguments equal to the specified value
23
* @param value Value to match against
24
* @param inverse If true, matches non-equal values
25
*/
26
fun <T> eq(value: T, inverse: Boolean = false): T
27
28
/**
29
* Matches arguments not equal to the specified value
30
* @param value Value to not match
31
*/
32
fun <T> neq(value: T): T
33
```
34
35
**Usage Examples:**
36
37
```kotlin
38
val userService = mockk<UserService>()
39
40
// Match any argument
41
every { userService.getUserById(any()) } returns User("default", "Default User")
42
43
// Match specific value
44
every { userService.getUserById(eq("123")) } returns User("123", "John")
45
46
// Match not equal to value
47
every { userService.getUserById(neq("admin")) } returns User("user", "Regular User")
48
49
// Use in verification
50
verify { userService.saveUser(any()) }
51
verify { userService.getUserById(eq("123")) }
52
```
53
54
### Reference Equality Matchers
55
56
Matchers based on reference equality rather than value equality.
57
58
```kotlin { .api }
59
/**
60
* Matches arguments with same reference as the specified value
61
* @param value Reference to match against
62
* @param inverse If true, matches different references
63
*/
64
fun <T> refEq(value: T, inverse: Boolean = false): T
65
66
/**
67
* Matches arguments with different reference than the specified value
68
* @param value Reference to not match
69
*/
70
fun <T> nrefEq(value: T): T
71
```
72
73
**Usage Examples:**
74
75
```kotlin
76
val userService = mockk<UserService>()
77
val specificUser = User("123", "John")
78
79
// Match same reference
80
every { userService.processUser(refEq(specificUser)) } returns "processed"
81
82
// Match different reference
83
every { userService.processUser(nrefEq(specificUser)) } returns "different object"
84
85
// Verification with reference equality
86
verify { userService.processUser(refEq(specificUser)) }
87
```
88
89
### Comparison Matchers
90
91
Matchers for numerical and comparable value comparisons.
92
93
```kotlin { .api }
94
/**
95
* Matches arguments greater than the specified value
96
* @param value Comparison value
97
* @param andEquals If true, includes equal values (>=)
98
*/
99
fun <T : Comparable<T>> more(value: T, andEquals: Boolean = false): T
100
101
/**
102
* Matches arguments less than the specified value
103
* @param value Comparison value
104
* @param andEquals If true, includes equal values (<=)
105
*/
106
fun <T : Comparable<T>> less(value: T, andEquals: Boolean = false): T
107
108
/**
109
* Matches arguments within the specified range
110
* @param from Range start value
111
* @param to Range end value
112
* @param fromInclusive Include start value (default: true)
113
* @param toInclusive Include end value (default: true)
114
*/
115
fun <T : Comparable<T>> range(
116
from: T,
117
to: T,
118
fromInclusive: Boolean = true,
119
toInclusive: Boolean = true
120
): T
121
122
/**
123
* Matches using Comparable.compareTo for equality
124
* @param value Value to compare against
125
*/
126
fun <T : Comparable<T>> cmpEq(value: T): T
127
```
128
129
**Usage Examples:**
130
131
```kotlin
132
val userService = mockk<UserService>()
133
134
// Numerical comparisons
135
every { userService.getUsersWithAge(more(18)) } returns listOf(/* adults */)
136
every { userService.getUsersWithAge(less(65, andEquals = true)) } returns listOf(/* non-seniors */)
137
every { userService.getUsersWithAge(range(18, 65)) } returns listOf(/* working age */)
138
139
// String comparisons
140
every { userService.getUsersWithNameAfter(more("M")) } returns listOf(/* names N-Z */)
141
142
// Verification with comparisons
143
verify { userService.processUsersWithScore(more(80)) }
144
```
145
146
### Type Checking Matchers
147
148
Matchers for type-based argument matching.
149
150
```kotlin { .api }
151
/**
152
* Matches arguments of the specified type
153
*/
154
inline fun <reified T> ofType(): T
155
156
/**
157
* Matches null values
158
* @param inverse If true, matches non-null values
159
*/
160
fun <T> isNull(inverse: Boolean = false): T?
161
```
162
163
**Usage Examples:**
164
165
```kotlin
166
val userService = mockk<UserService>()
167
168
// Match by type
169
every { userService.processEntity(ofType<User>()) } returns "user processed"
170
every { userService.processEntity(ofType<Admin>()) } returns "admin processed"
171
172
// Match null/non-null
173
every { userService.processOptionalData(isNull()) } returns "no data"
174
every { userService.processOptionalData(isNull(inverse = true)) } returns "has data"
175
176
// Verification with type matching
177
verify { userService.processEntity(ofType<User>()) }
178
```
179
180
### Logical Combinators
181
182
Matchers for combining multiple matching conditions.
183
184
```kotlin { .api }
185
/**
186
* Matches arguments that satisfy both matchers (logical AND)
187
* @param left First matcher
188
* @param right Second matcher
189
*/
190
fun <T> and(left: T, right: T): T
191
192
/**
193
* Matches arguments that satisfy either matcher (logical OR)
194
* @param left First matcher
195
* @param right Second matcher
196
*/
197
fun <T> or(left: T, right: T): T
198
199
/**
200
* Matches arguments that do NOT satisfy the matcher (logical NOT)
201
* @param value Matcher to negate
202
*/
203
fun <T> not(value: T): T
204
```
205
206
**Usage Examples:**
207
208
```kotlin
209
val userService = mockk<UserService>()
210
211
// Logical AND - age between 18-65 AND name starts with "J"
212
every {
213
userService.processUser(and(
214
match { it.age in 18..65 },
215
match { it.name.startsWith("J") }
216
))
217
} returns "processed special user"
218
219
// Logical OR - either admin or premium user
220
every {
221
userService.processUser(or(
222
match { it.type == UserType.ADMIN },
223
match { it.isPremium }
224
))
225
} returns "processed privileged user"
226
227
// Logical NOT - not a test user
228
every { userService.processUser(not(match { it.isTestUser })) } returns "processed real user"
229
```
230
231
### Capturing Matchers
232
233
Matchers that capture arguments for later inspection.
234
235
```kotlin { .api }
236
/**
237
* Captures argument to a list
238
* @param lst Mutable list to capture values into
239
*/
240
fun <T> capture(lst: MutableList<T>): T
241
242
/**
243
* Captures argument to a capturing slot
244
* @param slot CapturingSlot to capture value into
245
*/
246
fun <T> capture(slot: CapturingSlot<T>): T
247
248
/**
249
* Captures nullable argument to a list
250
* @param lst Mutable list to capture values into
251
*/
252
fun <T> captureNullable(lst: MutableList<T?>): T?
253
254
/**
255
* Captures nullable argument to a capturing slot
256
* @param slot CapturingSlot to capture value into
257
*/
258
fun <T> captureNullable(slot: CapturingSlot<T?>): T?
259
```
260
261
**Usage Examples:**
262
263
```kotlin
264
val userService = mockk<UserService>()
265
val capturedUsers = mutableListOf<User>()
266
val userSlot = slot<User>()
267
268
// Capture to list
269
every { userService.saveUser(capture(capturedUsers)) } returns "saved"
270
271
// Capture to slot
272
every { userService.updateUser(capture(userSlot)) } returns "updated"
273
274
// Make calls
275
userService.saveUser(User("1", "John"))
276
userService.saveUser(User("2", "Jane"))
277
userService.updateUser(User("3", "Bob"))
278
279
// Access captured values
280
val allSavedUsers = capturedUsers // [User("1", "John"), User("2", "Jane")]
281
val lastUpdatedUser = userSlot.captured // User("3", "Bob")
282
```
283
284
### Custom Matchers
285
286
Create custom matching logic using the match function.
287
288
```kotlin { .api }
289
/**
290
* Matches arguments using custom matcher logic
291
* @param matcher Custom Matcher implementation
292
*/
293
fun <T> match(matcher: Matcher<T>): T
294
295
/**
296
* Matches arguments using lambda-based matching
297
* @param predicate Lambda that returns true for matching arguments
298
*/
299
inline fun <reified T> match(noinline predicate: (T?) -> Boolean): T
300
301
interface Matcher<in T> {
302
fun match(arg: T?): Boolean
303
fun substitute(map: Map<Any, Any>): Matcher<T>
304
}
305
```
306
307
**Usage Examples:**
308
309
```kotlin
310
val userService = mockk<UserService>()
311
312
// Lambda-based matching
313
every {
314
userService.processUser(match { user ->
315
user != null && user.name.length > 5 && user.age > 18
316
})
317
} returns "processed valid user"
318
319
// Custom Matcher implementation
320
class EmailMatcher : Matcher<String> {
321
override fun match(arg: String?): Boolean {
322
return arg?.contains("@") == true
323
}
324
325
override fun substitute(map: Map<Any, Any>): Matcher<String> = this
326
}
327
328
every { userService.sendEmail(match(EmailMatcher())) } returns "email sent"
329
330
// Verification with custom matching
331
verify {
332
userService.processUser(match { it?.name?.startsWith("J") == true })
333
}
334
```
335
336
### Array and Collection Matchers
337
338
Specialized matchers for arrays and collections.
339
340
```kotlin { .api }
341
/**
342
* Matches any vararg arguments
343
*/
344
fun <T> anyVararg(): Array<T>
345
346
/**
347
* Matches varargs where all elements satisfy the condition
348
* @param matcher Matcher that all elements must satisfy
349
*/
350
fun <T> varargAll(matcher: T): Array<T>
351
352
/**
353
* Matches varargs where any element satisfies the condition
354
* @param matcher Matcher that at least one element must satisfy
355
*/
356
fun <T> varargAny(matcher: T): Array<T>
357
358
// Primitive array matchers
359
fun anyIntVararg(): IntArray
360
fun anyBooleanVararg(): BooleanArray
361
fun anyByteVararg(): ByteArray
362
fun anyCharVararg(): CharArray
363
fun anyShortVararg(): ShortArray
364
fun anyLongVararg(): LongArray
365
fun anyFloatVararg(): FloatArray
366
fun anyDoubleVararg(): DoubleArray
367
```
368
369
**Usage Examples:**
370
371
```kotlin
372
interface LogService {
373
fun log(level: String, vararg messages: String)
374
fun logNumbers(vararg numbers: Int)
375
}
376
377
val logService = mockk<LogService>()
378
379
// Match any varargs
380
every { logService.log("INFO", *anyVararg()) } just Runs
381
382
// Match varargs with conditions
383
every {
384
logService.log("ERROR", *varargAll(match { it.contains("error") }))
385
} just Runs
386
387
// Match primitive varargs
388
every { logService.logNumbers(*anyIntVararg()) } just Runs
389
390
// Verification with varargs
391
verify { logService.log("INFO", *anyVararg()) }
392
```
393
394
### Function and Lambda Matchers
395
396
Matchers for function types and lambda arguments.
397
398
```kotlin { .api }
399
/**
400
* Captures lambda functions for execution
401
*/
402
fun <T> captureLambda(): T
403
404
/**
405
* Captures coroutine functions
406
*/
407
fun <T> captureCoroutine(): T
408
409
/**
410
* Matches function invocations (up to 22 parameters)
411
*/
412
fun invoke(): Function0<*>
413
fun <T1> invoke(arg1: T1): Function1<T1, *>
414
fun <T1, T2> invoke(arg1: T1, arg2: T2): Function2<T1, T2, *>
415
// ... up to Function22
416
417
/**
418
* Matches coroutine function invocations
419
*/
420
fun coInvoke(): suspend () -> Any?
421
fun <T1> coInvoke(arg1: T1): suspend (T1) -> Any?
422
// ... and so on
423
```
424
425
**Usage Examples:**
426
427
```kotlin
428
interface CallbackService {
429
fun processWithCallback(data: String, callback: (String) -> Unit)
430
fun processAsync(data: String, callback: suspend (String) -> Unit)
431
}
432
433
val callbackService = mockk<CallbackService>()
434
val lambdaSlot = slot<(String) -> Unit>()
435
436
// Capture lambda for later execution
437
every {
438
callbackService.processWithCallback(any(), captureLambda())
439
} answers {
440
val callback = secondArg<(String) -> Unit>()
441
callback("processed: ${firstArg<String>()}")
442
}
443
444
// Match function invocation
445
every {
446
callbackService.processWithCallback("test", invoke("result"))
447
} just Runs
448
449
// Verification with function matching
450
verify {
451
callbackService.processWithCallback("test", invoke("result"))
452
}
453
```
454
455
### Universal Matchers
456
457
Matchers that handle special cases and universal matching.
458
459
```kotlin { .api }
460
/**
461
* Matches any argument (most permissive matcher)
462
*/
463
fun <T> allAny(): T
464
```
465
466
**Usage Examples:**
467
468
```kotlin
469
val userService = mockk<UserService>()
470
471
// Most permissive matching
472
every { userService.complexMethod(allAny(), allAny(), allAny()) } returns "result"
473
474
// Useful when exact matching is difficult
475
verify { userService.complexMethod(allAny(), allAny(), allAny()) }
476
```