0
# Test Stubs
1
2
Test stubs are spies with programmable behavior. They record calls like spies but also allow you to control return values, exceptions, and callback execution. Stubs are essential for isolating code under test from its dependencies.
3
4
## Capabilities
5
6
### Creating Stubs
7
8
Create stubs to replace functions with controlled behavior.
9
10
```javascript { .api }
11
/**
12
* Creates an anonymous stub with no default behavior
13
* @returns New stub function
14
*/
15
function stub(): SinonStub;
16
17
/**
18
* Replaces an object method with a stub
19
* @param object - Object containing the method to stub
20
* @param method - Method name to replace with stub
21
* @returns Stub replacing the original method
22
*/
23
function stub<T>(object: T, method: keyof T): SinonStub;
24
25
/**
26
* Replaces an object method with a stub that has custom implementation
27
* @param object - Object containing the method to stub
28
* @param method - Method name to replace
29
* @param func - Custom implementation for the stub
30
* @returns Stub with the provided implementation
31
*/
32
function stub<T>(object: T, method: keyof T, func: Function): SinonStub;
33
```
34
35
**Usage Examples:**
36
37
```javascript
38
import { stub } from "sinon";
39
40
// Anonymous stub
41
const callback = stub();
42
callback.returns("test value");
43
console.log(callback()); // "test value"
44
45
// Stub object method
46
const user = { getName: () => "John" };
47
const nameStub = stub(user, "getName");
48
nameStub.returns("Jane");
49
console.log(user.getName()); // "Jane"
50
51
// Stub with custom implementation
52
const mathStub = stub(Math, "random");
53
mathStub.callsFake(() => 0.5);
54
console.log(Math.random()); // 0.5
55
```
56
57
### Return Value Behaviors
58
59
Configure stubs to return specific values or follow patterns.
60
61
```javascript { .api }
62
interface SinonStub extends SinonSpy {
63
/**
64
* Make stub return a specific value
65
* @param value - Value to return when called
66
* @returns The stub for chaining
67
*/
68
returns(value: any): SinonStub;
69
70
/**
71
* Make stub return the argument at specified index
72
* @param index - Argument index to return
73
* @returns The stub for chaining
74
*/
75
returnsArg(index: number): SinonStub;
76
77
/**
78
* Make stub return the `this` context
79
* @returns The stub for chaining
80
*/
81
returnsThis(): SinonStub;
82
}
83
```
84
85
**Usage Examples:**
86
87
```javascript
88
const stub = sinon.stub();
89
90
// Return specific value
91
stub.returns(42);
92
console.log(stub()); // 42
93
94
// Return argument
95
stub.returnsArg(1);
96
console.log(stub("first", "second")); // "second"
97
98
// Return this context
99
const obj = { method: stub.returnsThis() };
100
console.log(obj.method() === obj); // true
101
```
102
103
### Exception Behaviors
104
105
Configure stubs to throw exceptions.
106
107
```javascript { .api }
108
interface SinonStub extends SinonSpy {
109
/**
110
* Make stub throw an exception
111
* @param error - Error to throw (creates generic Error if omitted)
112
* @returns The stub for chaining
113
*/
114
throws(error?: any): SinonStub;
115
116
/**
117
* Make stub throw an exception with specific type and message
118
* @param type - Error type name
119
* @param message - Error message
120
* @returns The stub for chaining
121
*/
122
throws(type: string, message?: string): SinonStub;
123
124
/**
125
* Make stub throw the argument at specified index
126
* @param index - Argument index to throw
127
* @returns The stub for chaining
128
*/
129
throwsArg(index: number): SinonStub;
130
}
131
```
132
133
**Usage Examples:**
134
135
```javascript
136
const stub = sinon.stub();
137
138
// Throw generic error
139
stub.throws();
140
// stub() throws Error
141
142
// Throw specific error
143
stub.throws(new TypeError("Invalid argument"));
144
// stub() throws TypeError: Invalid argument
145
146
// Throw with type and message
147
stub.throws("RangeError", "Value out of range");
148
// stub() throws RangeError: Value out of range
149
150
// Throw argument
151
stub.throwsArg(0);
152
// stub(new Error("test")) throws the provided error
153
```
154
155
### Promise Behaviors
156
157
Configure stubs to work with async/await and Promises.
158
159
```javascript { .api }
160
interface SinonStub extends SinonSpy {
161
/**
162
* Make stub return a resolved Promise
163
* @param value - Value to resolve with
164
* @returns The stub for chaining
165
*/
166
resolves(value?: any): SinonStub;
167
168
/**
169
* Make stub return a rejected Promise
170
* @param error - Error to reject with
171
* @returns The stub for chaining
172
*/
173
rejects(error?: any): SinonStub;
174
175
/**
176
* Make stub resolve with the argument at specified index
177
* @param index - Argument index to resolve with
178
* @returns The stub for chaining
179
*/
180
resolvesArg(index: number): SinonStub;
181
182
/**
183
* Make stub resolve with the `this` context
184
* @returns The stub for chaining
185
*/
186
resolvesThis(): SinonStub;
187
}
188
```
189
190
**Usage Examples:**
191
192
```javascript
193
const stub = sinon.stub();
194
195
// Resolve with value
196
stub.resolves({ data: "success" });
197
const result = await stub();
198
console.log(result); // { data: "success" }
199
200
// Reject with error
201
stub.rejects(new Error("API failed"));
202
try {
203
await stub();
204
} catch (error) {
205
console.log(error.message); // "API failed"
206
}
207
208
// Resolve with argument
209
stub.resolvesArg(0);
210
const data = await stub("hello world");
211
console.log(data); // "hello world"
212
```
213
214
### Callback Behaviors
215
216
Configure stubs to call functions passed as arguments (callbacks).
217
218
```javascript { .api }
219
interface SinonStub extends SinonSpy {
220
/**
221
* Make stub call the callback at specified argument index
222
* @param index - Argument index of the callback function
223
* @returns The stub for chaining
224
*/
225
callsArg(index: number): SinonStub;
226
227
/**
228
* Make stub call the callback with specific arguments
229
* @param index - Argument index of the callback function
230
* @param args - Arguments to pass to the callback
231
* @returns The stub for chaining
232
*/
233
callsArgWith(index: number, ...args: any[]): SinonStub;
234
235
/**
236
* Make stub call the callback with specific `this` context
237
* @param index - Argument index of the callback function
238
* @param context - `this` context for the callback
239
* @returns The stub for chaining
240
*/
241
callsArgOn(index: number, context: any): SinonStub;
242
243
/**
244
* Make stub call the callback with context and arguments
245
* @param index - Argument index of the callback function
246
* @param context - `this` context for the callback
247
* @param args - Arguments to pass to the callback
248
* @returns The stub for chaining
249
*/
250
callsArgOnWith(index: number, context: any, ...args: any[]): SinonStub;
251
252
/**
253
* Make stub call the first callback argument (leftmost)
254
* @param args - Arguments to pass to the callback
255
* @returns The stub for chaining
256
*/
257
yields(...args: any[]): SinonStub;
258
259
/**
260
* Make stub call the last callback argument (rightmost)
261
* @param args - Arguments to pass to the callback
262
* @returns The stub for chaining
263
*/
264
yieldsRight(...args: any[]): SinonStub;
265
266
/**
267
* Make stub call the first callback with specific `this` context
268
* @param context - `this` context for the callback
269
* @param args - Arguments to pass to the callback
270
* @returns The stub for chaining
271
*/
272
yieldsOn(context: any, ...args: any[]): SinonStub;
273
274
/**
275
* Make stub call a callback property with arguments
276
* @param property - Property name containing the callback
277
* @param args - Arguments to pass to the callback
278
* @returns The stub for chaining
279
*/
280
yieldsTo(property: string, ...args: any[]): SinonStub;
281
282
/**
283
* Make stub call a callback property with context and arguments
284
* @param property - Property name containing the callback
285
* @param context - `this` context for the callback
286
* @param args - Arguments to pass to the callback
287
* @returns The stub for chaining
288
*/
289
yieldsToOn(property: string, context: any, ...args: any[]): SinonStub;
290
}
291
```
292
293
**Usage Examples:**
294
295
```javascript
296
const stub = sinon.stub();
297
298
// Call callback at index 1
299
stub.callsArg(1);
300
stub("first", (x) => console.log(x)); // Callback called with undefined
301
302
// Call callback with arguments
303
stub.callsArgWith(0, "hello", "world");
304
stub((a, b) => console.log(a, b)); // Logs: "hello world"
305
306
// Call first callback found
307
stub.yields("error", null);
308
stub(null, (err, data) => {
309
console.log(err, data); // Logs: "error" null
310
});
311
312
// Call callback property
313
const options = { success: (data) => console.log(data) };
314
stub.yieldsTo("success", "completed");
315
stub(options); // Logs: "completed"
316
```
317
318
### Async Callback Behaviors
319
320
Asynchronous versions of callback behaviors.
321
322
```javascript { .api }
323
interface SinonStub extends SinonSpy {
324
/**
325
* Make stub call callback asynchronously at next tick
326
* @param index - Argument index of the callback function
327
* @returns The stub for chaining
328
*/
329
callsArgAsync(index: number): SinonStub;
330
331
/**
332
* Make stub call callback asynchronously with arguments
333
* @param index - Argument index of the callback function
334
* @param args - Arguments to pass to the callback
335
* @returns The stub for chaining
336
*/
337
callsArgWithAsync(index: number, ...args: any[]): SinonStub;
338
339
/**
340
* Make stub call callback asynchronously with context
341
* @param index - Argument index of the callback function
342
* @param context - `this` context for the callback
343
* @returns The stub for chaining
344
*/
345
callsArgOnAsync(index: number, context: any): SinonStub;
346
347
/**
348
* Make stub call callback asynchronously with context and arguments
349
* @param index - Argument index of the callback function
350
* @param context - `this` context for the callback
351
* @param args - Arguments to pass to the callback
352
* @returns The stub for chaining
353
*/
354
callsArgOnWithAsync(index: number, context: any, ...args: any[]): SinonStub;
355
356
/**
357
* Make stub call first callback asynchronously
358
* @param args - Arguments to pass to the callback
359
* @returns The stub for chaining
360
*/
361
yieldsAsync(...args: any[]): SinonStub;
362
363
/**
364
* Make stub call first callback asynchronously with context
365
* @param context - `this` context for the callback
366
* @param args - Arguments to pass to the callback
367
* @returns The stub for chaining
368
*/
369
yieldsOnAsync(context: any, ...args: any[]): SinonStub;
370
371
/**
372
* Make stub call callback property asynchronously
373
* @param property - Property name containing the callback
374
* @param args - Arguments to pass to the callback
375
* @returns The stub for chaining
376
*/
377
yieldsToAsync(property: string, ...args: any[]): SinonStub;
378
379
/**
380
* Make stub call callback property asynchronously with context
381
* @param property - Property name containing the callback
382
* @param context - `this` context for the callback
383
* @param args - Arguments to pass to the callback
384
* @returns The stub for chaining
385
*/
386
yieldsToOnAsync(property: string, context: any, ...args: any[]): SinonStub;
387
}
388
```
389
390
### Custom Implementation Behaviors
391
392
Configure stubs with custom implementations or pass-through behavior.
393
394
```javascript { .api }
395
interface SinonStub extends SinonSpy {
396
/**
397
* Make stub call a custom function when invoked
398
* @param func - Custom function implementation
399
* @returns The stub for chaining
400
*/
401
callsFake(func: Function): SinonStub;
402
403
/**
404
* Make stub call the original method (if stubbing object method)
405
* @returns The stub for chaining
406
*/
407
callsThrough(): SinonStub;
408
409
/**
410
* Make stub call the original method when used as constructor
411
* @returns The stub for chaining
412
*/
413
callsThroughWithNew(): SinonStub;
414
}
415
```
416
417
**Usage Examples:**
418
419
```javascript
420
// Custom implementation
421
const stub = sinon.stub();
422
stub.callsFake((x, y) => x + y);
423
console.log(stub(2, 3)); // 5
424
425
// Call through to original
426
const obj = { method: (x) => x * 2 };
427
const stub = sinon.stub(obj, "method");
428
stub.callsThrough(); // Calls original implementation
429
console.log(obj.method(5)); // 10 (original behavior)
430
```
431
432
### Conditional Behaviors
433
434
Configure different behaviors for specific calls or arguments.
435
436
```javascript { .api }
437
interface SinonStub extends SinonSpy {
438
/**
439
* Configure behavior for calls with specific arguments
440
* @param args - Arguments that trigger this behavior
441
* @returns Stub configured for these arguments
442
*/
443
withArgs(...args: any[]): SinonStub;
444
445
/**
446
* Configure behavior for a specific call number
447
* @param index - Zero-based call index
448
* @returns Stub configured for this call
449
*/
450
onCall(index: number): SinonStub;
451
452
/**
453
* Configure behavior for the first call
454
* @returns Stub configured for first call
455
*/
456
onFirstCall(): SinonStub;
457
458
/**
459
* Configure behavior for the second call
460
* @returns Stub configured for second call
461
*/
462
onSecondCall(): SinonStub;
463
464
/**
465
* Configure behavior for the third call
466
* @returns Stub configured for third call
467
*/
468
onThirdCall(): SinonStub;
469
}
470
```
471
472
**Usage Examples:**
473
474
```javascript
475
const stub = sinon.stub();
476
477
// Different behavior for different arguments
478
stub.withArgs("hello").returns("world");
479
stub.withArgs("foo").returns("bar");
480
console.log(stub("hello")); // "world"
481
console.log(stub("foo")); // "bar"
482
483
// Different behavior for different calls
484
stub.onFirstCall().returns("first");
485
stub.onSecondCall().returns("second");
486
stub.onThirdCall().throws();
487
console.log(stub()); // "first"
488
console.log(stub()); // "second"
489
// stub(); // throws
490
```
491
492
### Property Behaviors
493
494
Configure stubs for object property access (getters/setters).
495
496
```javascript { .api }
497
interface SinonStub extends SinonSpy {
498
/**
499
* Configure stub as a getter that returns value when property is accessed
500
* @param func - Getter function
501
* @returns The stub for chaining
502
*/
503
get(func: () => any): SinonStub;
504
505
/**
506
* Configure stub as a setter that calls function when property is set
507
* @param func - Setter function
508
* @returns The stub for chaining
509
*/
510
set(func: (value: any) => void): SinonStub;
511
512
/**
513
* Configure stub as a property with a specific value
514
* @param value - Property value
515
* @returns The stub for chaining
516
*/
517
value(value: any): SinonStub;
518
}
519
```
520
521
### Stub Lifecycle
522
523
Methods for managing stub state and behavior.
524
525
```javascript { .api }
526
interface SinonStub extends SinonSpy {
527
/**
528
* Reset all stub behaviors to default (but keep call history)
529
*/
530
resetBehavior(): void;
531
532
/**
533
* Reset call history (but keep behaviors)
534
*/
535
resetHistory(): void;
536
537
/**
538
* Reset both behaviors and call history
539
*/
540
reset(): void;
541
542
/**
543
* Restore original method (for stubs on object methods)
544
*/
545
restore(): void;
546
}
547
```
548
549
**Usage Examples:**
550
551
```javascript
552
const obj = { method: () => "original" };
553
const stub = sinon.stub(obj, "method");
554
555
// Configure behavior
556
stub.returns("stubbed");
557
console.log(obj.method()); // "stubbed"
558
559
// Reset behavior but keep history
560
stub.resetBehavior();
561
console.log(obj.method()); // "original" (back to original)
562
console.log(stub.called); // true (history preserved)
563
564
// Reset everything
565
stub.reset();
566
console.log(stub.called); // false (history cleared)
567
568
// Restore original method
569
stub.restore();
570
// obj.method is now completely restored
571
```
572
573
## Types
574
575
```javascript { .api }
576
// Stub extends all spy functionality
577
interface SinonStub extends SinonSpy {
578
// All stub-specific methods documented above
579
}
580
581
// Generic stub interface for typed functions
582
interface SinonStub<F extends Function = Function> extends SinonStub {
583
(...args: Parameters<F>): ReturnType<F>;
584
}
585
```