0
# Argument Capturing
1
2
Type-safe argument capturing with Kotlin-friendly APIs and support for multiple argument capture patterns. Essential for capturing and inspecting arguments passed to mock methods.
3
4
## Capabilities
5
6
### Basic Argument Captors
7
8
Functions for creating argument captors for different numbers of types.
9
10
```kotlin { .api }
11
/**
12
* Creates a KArgumentCaptor for the specified reified type
13
* @returns KArgumentCaptor instance for capturing arguments of type T
14
*/
15
inline fun <reified T : Any> argumentCaptor(): KArgumentCaptor<T>
16
17
/**
18
* Creates 2 KArgumentCaptors for given types
19
* @param a KClass for first type (defaults to reified A::class)
20
* @param b KClass for second type (defaults to reified B::class)
21
* @returns Pair of KArgumentCaptors for types A and B
22
*/
23
inline fun <reified A : Any, reified B : Any> argumentCaptor(
24
a: KClass<A> = A::class,
25
b: KClass<B> = B::class
26
): Pair<KArgumentCaptor<A>, KArgumentCaptor<B>>
27
28
/**
29
* Creates 3 KArgumentCaptors for given types
30
* @param a KClass for first type (defaults to reified A::class)
31
* @param b KClass for second type (defaults to reified B::class)
32
* @param c KClass for third type (defaults to reified C::class)
33
* @returns Triple of KArgumentCaptors for types A, B, and C
34
*/
35
inline fun <reified A : Any, reified B : Any, reified C : Any> argumentCaptor(
36
a: KClass<A> = A::class,
37
b: KClass<B> = B::class,
38
c: KClass<C> = C::class
39
): Triple<KArgumentCaptor<A>, KArgumentCaptor<B>, KArgumentCaptor<C>>
40
```
41
42
**Usage Examples:**
43
44
```kotlin
45
import com.nhaarman.mockitokotlin2.*
46
47
// Single argument captor
48
val userCaptor = argumentCaptor<User>()
49
verify(userService).saveUser(userCaptor.capture())
50
val capturedUser = userCaptor.firstValue
51
52
// Multiple argument captors
53
val (userCaptor, emailCaptor) = argumentCaptor<User, String>()
54
verify(emailService).sendEmail(userCaptor.capture(), emailCaptor.capture())
55
val capturedUser = userCaptor.firstValue
56
val capturedEmail = emailCaptor.firstValue
57
58
// Three argument captors
59
val (userCaptor, emailCaptor, templateCaptor) = argumentCaptor<User, String, EmailTemplate>()
60
verify(emailService).sendTemplatedEmail(
61
userCaptor.capture(),
62
emailCaptor.capture(),
63
templateCaptor.capture()
64
)
65
```
66
67
### Extended Argument Captors
68
69
Argument captors for larger numbers of parameters using holder classes.
70
71
```kotlin { .api }
72
/**
73
* Creates 4 KArgumentCaptors for given types
74
* @param a KClass for first type (defaults to reified A::class)
75
* @param b KClass for second type (defaults to reified B::class)
76
* @param c KClass for third type (defaults to reified C::class)
77
* @param d KClass for fourth type (defaults to reified D::class)
78
* @returns ArgumentCaptorHolder4 containing 4 KArgumentCaptors
79
*/
80
inline fun <reified A : Any, reified B : Any, reified C : Any, reified D : Any> argumentCaptor(
81
a: KClass<A> = A::class,
82
b: KClass<B> = B::class,
83
c: KClass<C> = C::class,
84
d: KClass<D> = D::class
85
): ArgumentCaptorHolder4<KArgumentCaptor<A>, KArgumentCaptor<B>, KArgumentCaptor<C>, KArgumentCaptor<D>>
86
87
/**
88
* Creates 5 KArgumentCaptors for given types
89
* @param a KClass for first type (defaults to reified A::class)
90
* @param b KClass for second type (defaults to reified B::class)
91
* @param c KClass for third type (defaults to reified C::class)
92
* @param d KClass for fourth type (defaults to reified D::class)
93
* @param e KClass for fifth type (defaults to reified E::class)
94
* @returns ArgumentCaptorHolder5 containing 5 KArgumentCaptors
95
*/
96
inline fun <reified A : Any, reified B : Any, reified C : Any, reified D : Any, reified E : Any> argumentCaptor(
97
a: KClass<A> = A::class,
98
b: KClass<B> = B::class,
99
c: KClass<C> = C::class,
100
d: KClass<D> = D::class,
101
e: KClass<E> = E::class
102
): ArgumentCaptorHolder5<KArgumentCaptor<A>, KArgumentCaptor<B>, KArgumentCaptor<C>, KArgumentCaptor<D>, KArgumentCaptor<E>>
103
```
104
105
**Usage Examples:**
106
107
```kotlin
108
import com.nhaarman.mockitokotlin2.*
109
110
// Four argument captors
111
val captors = argumentCaptor<String, Int, Boolean, Double>()
112
verify(complexService).processData(
113
captors.first.capture(),
114
captors.second.capture(),
115
captors.third.capture(),
116
captors.fourth.capture()
117
)
118
119
// Five argument captors with destructuring
120
val (nameCaptor, ageCaptor, activeCaptor, salaryCaptor, dateCaptor) =
121
argumentCaptor<String, Int, Boolean, Double, LocalDate>()
122
```
123
124
### Lambda-Based Argument Captors
125
126
Argument captors with immediate lambda evaluation for verification.
127
128
```kotlin { .api }
129
/**
130
* Creates a KArgumentCaptor with immediate lambda evaluation for fast verification
131
* @param f Lambda function applied to the created captor
132
* @returns KArgumentCaptor instance after applying the lambda
133
*/
134
inline fun <reified T : Any> argumentCaptor(f: KArgumentCaptor<T>.() -> Unit): KArgumentCaptor<T>
135
```
136
137
**Usage Examples:**
138
139
```kotlin
140
import com.nhaarman.mockitokotlin2.*
141
142
// Captor with immediate verification
143
val userCaptor = argumentCaptor<User> {
144
verify(userService).saveUser(capture())
145
// Can access captured values immediately
146
assertThat(firstValue.email).isNotEmpty()
147
}
148
```
149
150
### Nullable Argument Captors
151
152
Special argument captors for nullable types.
153
154
```kotlin { .api }
155
/**
156
* Creates a KArgumentCaptor for nullable type
157
* @returns KArgumentCaptor instance for capturing nullable arguments of type T
158
*/
159
inline fun <reified T : Any> nullableArgumentCaptor(): KArgumentCaptor<T?>
160
161
/**
162
* Creates a KArgumentCaptor for nullable type with immediate lambda evaluation
163
* @param f Lambda function applied to the created captor
164
* @returns KArgumentCaptor instance for nullable type after applying the lambda
165
*/
166
inline fun <reified T : Any> nullableArgumentCaptor(f: KArgumentCaptor<T?>.() -> Unit): KArgumentCaptor<T?>
167
```
168
169
**Usage Examples:**
170
171
```kotlin
172
import com.nhaarman.mockitokotlin2.*
173
174
// Nullable argument captor
175
val nullableUserCaptor = nullableArgumentCaptor<User>()
176
verify(userService).updateUser(nullableUserCaptor.capture())
177
val capturedUser = nullableUserCaptor.firstValue // Can be null
178
179
// Nullable captor with lambda
180
val nullableCaptor = nullableArgumentCaptor<String> {
181
verify(service).processOptionalData(capture())
182
// Handle null case
183
firstValue?.let {
184
assertThat(it).isNotEmpty()
185
}
186
}
187
```
188
189
### Capture Helper Function
190
191
Utility function for capturing arguments directly.
192
193
```kotlin { .api }
194
/**
195
* Alias for ArgumentCaptor.capture() with null safety
196
* @param captor The ArgumentCaptor to use for capturing
197
* @returns Captured value or created instance if null
198
*/
199
inline fun <reified T : Any> capture(captor: ArgumentCaptor<T>): T
200
```
201
202
**Usage Examples:**
203
204
```kotlin
205
import com.nhaarman.mockitokotlin2.*
206
import org.mockito.ArgumentCaptor
207
208
// Using with standard Mockito ArgumentCaptor
209
val javaCaptor = ArgumentCaptor.forClass(User::class.java)
210
verify(userService).saveUser(capture(javaCaptor))
211
val capturedUser = javaCaptor.value
212
```
213
214
### KArgumentCaptor Class
215
216
Kotlin wrapper for ArgumentCaptor providing enhanced functionality.
217
218
```kotlin { .api }
219
/**
220
* Kotlin wrapper for ArgumentCaptor with enhanced functionality and null safety
221
*/
222
class KArgumentCaptor<out T : Any?>(
223
private val captor: ArgumentCaptor<T>,
224
private val tClass: KClass<*>
225
) {
226
/**
227
* The first captured value of the argument
228
* @throws IndexOutOfBoundsException if the value is not available
229
*/
230
val firstValue: T
231
232
/**
233
* The second captured value of the argument
234
* @throws IndexOutOfBoundsException if the value is not available
235
*/
236
val secondValue: T
237
238
/**
239
* The third captured value of the argument
240
* @throws IndexOutOfBoundsException if the value is not available
241
*/
242
val thirdValue: T
243
244
/**
245
* The last captured value of the argument
246
* @throws IndexOutOfBoundsException if the value is not available
247
*/
248
val lastValue: T
249
250
/**
251
* All captured values as a list
252
*/
253
val allValues: List<T>
254
255
/**
256
* Captures an argument for the associated method parameter
257
* @returns Captured value or created instance if null
258
*/
259
fun capture(): T
260
}
261
```
262
263
**Usage Examples:**
264
265
```kotlin
266
import com.nhaarman.mockitokotlin2.*
267
268
val userCaptor = argumentCaptor<User>()
269
270
// Capture multiple calls
271
verify(userService, times(3)).saveUser(userCaptor.capture())
272
273
// Access different captured values
274
val firstUser = userCaptor.firstValue
275
val secondUser = userCaptor.secondValue
276
val thirdUser = userCaptor.thirdValue
277
val lastUser = userCaptor.lastValue
278
279
// Access all captured values
280
val allUsers = userCaptor.allValues
281
assertThat(allUsers).hasSize(3)
282
283
// Verify properties of captured arguments
284
assertThat(firstUser.email).contains("@")
285
assertThat(allUsers).allMatch { it.age >= 18 }
286
```
287
288
### Argument Captor Holder Classes
289
290
Helper classes for managing multiple argument captors.
291
292
```kotlin { .api }
293
/**
294
* Holder class for 4 argument captors with component access
295
*/
296
class ArgumentCaptorHolder4<out A, out B, out C, out D>(
297
val first: A,
298
val second: B,
299
val third: C,
300
val fourth: D
301
) {
302
operator fun component1(): A
303
operator fun component2(): B
304
operator fun component3(): C
305
operator fun component4(): D
306
}
307
308
/**
309
* Holder class for 5 argument captors with component access
310
*/
311
class ArgumentCaptorHolder5<out A, out B, out C, out D, out E>(
312
val first: A,
313
val second: B,
314
val third: C,
315
val fourth: D,
316
val fifth: E
317
) {
318
operator fun component1(): A
319
operator fun component2(): B
320
operator fun component3(): C
321
operator fun component4(): D
322
operator fun component5(): E
323
}
324
```
325
326
**Usage Examples:**
327
328
```kotlin
329
import com.nhaarman.mockitokotlin2.*
330
331
// Using holder classes with destructuring
332
val (nameCaptor, ageCaptor, emailCaptor, activeCaptor) =
333
argumentCaptor<String, Int, String, Boolean>()
334
335
verify(userService).createUser(
336
nameCaptor.capture(),
337
ageCaptor.capture(),
338
emailCaptor.capture(),
339
activeCaptor.capture()
340
)
341
342
// Access via properties
343
val holder = argumentCaptor<String, Int, String, Boolean>()
344
verify(userService).createUser(
345
holder.first.capture(),
346
holder.second.capture(),
347
holder.third.capture(),
348
holder.fourth.capture()
349
)
350
```
351
352
### Extension Properties
353
354
Extension properties for standard Mockito ArgumentCaptor to match KArgumentCaptor functionality.
355
356
```kotlin { .api }
357
/**
358
* Extension property for first captured value
359
*/
360
val <T> ArgumentCaptor<T>.firstValue: T
361
362
/**
363
* Extension property for second captured value
364
*/
365
val <T> ArgumentCaptor<T>.secondValue: T
366
367
/**
368
* Extension property for third captured value
369
*/
370
val <T> ArgumentCaptor<T>.thirdValue: T
371
372
/**
373
* Extension property for last captured value
374
*/
375
val <T> ArgumentCaptor<T>.lastValue: T
376
```
377
378
**Usage Examples:**
379
380
```kotlin
381
import com.nhaarman.mockitokotlin2.*
382
import org.mockito.ArgumentCaptor
383
384
// Using extensions with standard ArgumentCaptor
385
val javaCaptor = ArgumentCaptor.forClass(String::class.java)
386
verify(service, times(3)).processString(javaCaptor.capture())
387
388
val firstString = javaCaptor.firstValue
389
val lastString = javaCaptor.lastValue
390
val allStrings = javaCaptor.allValues
391
```
392
393
## Types
394
395
```kotlin { .api }
396
// From org.mockito
397
class ArgumentCaptor<T>
398
interface KClass<T>
399
400
// From mockito-kotlin
401
class KArgumentCaptor<out T : Any?>(
402
private val captor: ArgumentCaptor<T>,
403
private val tClass: KClass<*>
404
) {
405
val firstValue: T
406
val secondValue: T
407
val thirdValue: T
408
val lastValue: T
409
val allValues: List<T>
410
fun capture(): T
411
}
412
413
class ArgumentCaptorHolder4<out A, out B, out C, out D>(
414
val first: A,
415
val second: B,
416
val third: C,
417
val fourth: D
418
)
419
420
class ArgumentCaptorHolder5<out A, out B, out C, out D, out E>(
421
val first: A,
422
val second: B,
423
val third: C,
424
val fourth: D,
425
val fifth: E
426
)
427
```