0
# Stubbing
1
2
Behavior definition system for specifying how mocks should respond to method calls, with comprehensive support for return values, exceptions, custom answers, and coroutine operations.
3
4
## Capabilities
5
6
### Basic Stubbing
7
8
Core stubbing functions for defining mock behavior.
9
10
```kotlin { .api }
11
/**
12
* Starts a stubbing block for defining mock behavior
13
* @param stubBlock Block containing the method call to stub
14
* @return MockKStubScope for specifying the response
15
*/
16
fun <T> every(stubBlock: MockKMatcherScope.() -> T): MockKStubScope<T, T>
17
18
/**
19
* Coroutine version of every for suspend functions
20
* @param stubBlock Block containing the suspend method call to stub
21
* @return MockKStubScope for specifying the response
22
*/
23
fun <T> coEvery(stubBlock: suspend MockKMatcherScope.() -> T): MockKStubScope<T, T>
24
25
/**
26
* Shortcut for stubbing Unit-returning functions
27
* @param stubBlock Block containing the Unit method call to stub
28
*/
29
fun justRun(stubBlock: MockKMatcherScope.() -> Unit)
30
31
/**
32
* Coroutine version of justRun for suspend Unit functions
33
* @param stubBlock Block containing the suspend Unit method call to stub
34
*/
35
fun coJustRun(stubBlock: suspend MockKMatcherScope.() -> Unit)
36
```
37
38
**Usage Examples:**
39
40
```kotlin
41
val userService = mockk<UserService>()
42
43
// Basic return value stubbing
44
every { userService.getUserById("123") } returns User("123", "John")
45
46
// Coroutine stubbing
47
every { userService.getUserByIdAsync("123") } returns User("123", "John")
48
49
// Unit function stubbing
50
justRun { userService.deleteUser("123") }
51
52
// Suspend unit function stubbing
53
coJustRun { userService.deleteUserAsync("123") }
54
```
55
56
### Stub Responses
57
58
Different ways to specify how stubbed methods should respond.
59
60
```kotlin { .api }
61
interface MockKStubScope<T, B> {
62
/** Returns a constant value */
63
infix fun returns(returnValue: T): MockKAdditionalAnswerScope<T, B>
64
65
/** Returns different values in sequence */
66
infix fun returnsMany(values: List<T>): MockKAdditionalAnswerScope<T, B>
67
68
/** Returns the nth argument passed to the method */
69
infix fun returnsArgument(n: Int): MockKAdditionalAnswerScope<T, B>
70
71
/** Throws an exception */
72
infix fun throws(ex: Throwable): MockKAdditionalAnswerScope<T, B>
73
74
/** Throws different exceptions in sequence */
75
infix fun throwsMany(exList: List<Throwable>): MockKAdditionalAnswerScope<T, B>
76
77
/** Provides a custom answer implementation */
78
infix fun answers(answer: Answer<T>): MockKAdditionalAnswerScope<T, B>
79
80
/** Provides a lambda-based answer */
81
infix fun answers(answer: MockKAnswerScope<T, B>.(Call) -> T): MockKAdditionalAnswerScope<T, B>
82
83
/** Provides a coroutine-based answer */
84
infix fun coAnswers(answer: suspend MockKAnswerScope<T, B>.(Call) -> T): MockKAdditionalAnswerScope<T, B>
85
}
86
```
87
88
**Usage Examples:**
89
90
```kotlin
91
val userService = mockk<UserService>()
92
93
// Return constant value
94
every { userService.getUserById(any()) } returns User("123", "John")
95
96
// Return sequence of values
97
every { userService.getNextId() } returnsMany listOf("1", "2", "3")
98
99
// Return argument
100
every { userService.echoId(any()) } returnsArgument 0
101
102
// Throw exception
103
every { userService.getUserById("invalid") } throws UserNotFoundException()
104
105
// Throw sequence of exceptions
106
every { userService.unstableOperation() } throwsMany listOf(
107
NetworkException(),
108
TimeoutException()
109
)
110
111
// Custom answer with call information
112
every { userService.processUser(any()) } answers {
113
val user = firstArg<User>()
114
User(user.id, user.name.uppercase())
115
}
116
117
// Coroutine answer
118
coEvery { userService.processUserAsync(any()) } coAnswers {
119
delay(100)
120
val user = firstArg<User>()
121
User(user.id, user.name.uppercase())
122
}
123
```
124
125
### Answer Scopes
126
127
Access to call information within custom answers.
128
129
```kotlin { .api }
130
abstract class MockKAnswerScope<T, B> {
131
/** Current call information */
132
val call: Call
133
134
/** Arguments passed to the method */
135
val args: List<Any?>
136
137
/** Number of arguments */
138
val nArgs: Int
139
140
/** Mock object being called */
141
val self: Any
142
143
/** Method being called */
144
val method: MethodDescription
145
146
/** Access to first argument with type casting */
147
fun <T> firstArg(): T
148
149
/** Access to second argument with type casting */
150
fun <T> secondArg(): T
151
152
/** Access to third argument with type casting */
153
fun <T> thirdArg(): T
154
155
/** Access to last argument with type casting */
156
fun <T> lastArg(): T
157
158
/** Access to nth argument with type casting */
159
fun <T> arg(n: Int): T
160
161
/** For spies - calls the original implementation */
162
fun callOriginal(): T
163
}
164
```
165
166
**Usage Examples:**
167
168
```kotlin
169
val userService = spyk<UserService>()
170
171
// Access arguments in answer
172
every { userService.createUser(any(), any()) } answers {
173
val name = firstArg<String>()
174
val email = secondArg<String>()
175
User(generateId(), name, email)
176
}
177
178
// Call original implementation (for spies)
179
every { userService.validateUser(any()) } answers {
180
val user = firstArg<User>()
181
if (user.id == "test") {
182
true // Custom behavior for test user
183
} else {
184
callOriginal() // Use real implementation
185
}
186
}
187
188
// Access call metadata
189
every { userService.logOperation(any()) } answers {
190
val operation = firstArg<String>()
191
logger.info("Mock ${method.name} called with: $operation")
192
callOriginal()
193
}
194
```
195
196
### Special Answer Types
197
198
Pre-built answer implementations for common scenarios.
199
200
```kotlin { .api }
201
object Runs
202
object Awaits
203
204
// Used with 'just' infix function
205
infix fun MockKStubScope<Unit, *>.just(runs: Runs)
206
infix fun MockKStubScope<Unit, *>.just(awaits: Awaits)
207
```
208
209
**Usage Examples:**
210
211
```kotlin
212
// Equivalent to justRun
213
every { userService.deleteUser(any()) } just Runs
214
215
// For suspend functions that never return
216
coEvery { userService.waitForever() } just Awaits
217
```
218
219
### Argument Capture in Stubbing
220
221
Capturing arguments during stubbing for later inspection.
222
223
```kotlin { .api }
224
/**
225
* Creates a capturing slot for single values
226
*/
227
inline fun <reified T : Any?> slot(): CapturingSlot<T>
228
229
class CapturingSlot<T> {
230
val captured: T
231
val isCaptured: Boolean
232
val isNull: Boolean
233
fun clear()
234
}
235
```
236
237
**Usage Examples:**
238
239
```kotlin
240
val userService = mockk<UserService>()
241
val userSlot = slot<User>()
242
val idSlot = slot<String>()
243
244
// Capture argument during stubbing
245
every { userService.saveUser(capture(userSlot)) } returns "user-id"
246
every { userService.getUserById(capture(idSlot)) } returns User("123", "John")
247
248
// Use the mock
249
userService.saveUser(User("123", "John"))
250
userService.getUserById("123")
251
252
// Access captured values
253
val capturedUser = userSlot.captured // User("123", "John")
254
val capturedId = idSlot.captured // "123"
255
```
256
257
### Property Stubbing
258
259
Stubbing property access on mocks.
260
261
```kotlin { .api }
262
interface MockKStubScope<T, B> {
263
/** Specify property type for proper stubbing */
264
fun <K> propertyType(): MockKStubScope<K, B>
265
266
/** Specify nullable property type */
267
fun <K> nullablePropertyType(): MockKStubScope<K?, B>
268
}
269
```
270
271
**Usage Examples:**
272
273
```kotlin
274
val userService = mockk<UserService>()
275
276
// Property getter stubbing
277
every { userService.currentUser } returns User("123", "John")
278
279
// Property setter stubbing
280
every { userService.currentUser = any() } just Runs
281
282
// Property with type specification
283
every { userService.userCount } propertyType<Int>() returns 42
284
```
285
286
### Chained Stubbing
287
288
Multiple stub configurations for the same method call.
289
290
```kotlin { .api }
291
interface MockKAdditionalAnswerScope<T, B> {
292
/** Add another answer that will be used in subsequent calls */
293
infix fun andThen(answer: T): MockKAdditionalAnswerScope<T, B>
294
295
/** Add another answer with different behavior */
296
infix fun andThenThrows(ex: Throwable): MockKAdditionalAnswerScope<T, B>
297
}
298
```
299
300
**Usage Examples:**
301
302
```kotlin
303
val userService = mockk<UserService>()
304
305
// Chain different responses
306
every { userService.getUser() } returns User("1", "John") andThen User("2", "Jane")
307
308
// Mix returns and exceptions
309
every { userService.unstableOperation() } returns "success" andThenThrows NetworkException()
310
311
// Complex chaining
312
every { userService.getData() } returns "data1" andThen "data2" andThenThrows TimeoutException()
313
```