0
# Test Mocks
1
2
Test mocks provide pre-programmed expectations for verifying that code interacts with dependencies correctly. Unlike spies and stubs, mocks define expected behavior upfront and verify that those expectations are met.
3
4
## Capabilities
5
6
### Creating Mocks
7
8
Create mock objects with expectations for method calls.
9
10
```javascript { .api }
11
/**
12
* Creates a mock for an object, allowing expectations to be set on its methods
13
* @param object - Object to create mock for
14
* @returns Mock object for setting expectations
15
*/
16
function mock(object: any): SinonMock;
17
18
/**
19
* Creates an anonymous mock with a name for better error messages
20
* @param name - Name for the anonymous mock
21
* @returns Anonymous mock expectation
22
*/
23
function mock(name?: string): SinonExpectation;
24
```
25
26
**Usage Examples:**
27
28
```javascript
29
import { mock } from "sinon";
30
31
// Mock an object
32
const user = { getName: () => "John", setName: (name) => {} };
33
const userMock = mock(user);
34
35
// Anonymous mock
36
const callback = mock("callback");
37
```
38
39
### Mock Object Interface
40
41
Interface for managing mocks on objects with multiple methods.
42
43
```javascript { .api }
44
interface SinonMock {
45
/**
46
* Create an expectation for a specific method
47
* @param method - Method name to create expectation for
48
* @returns Expectation object for configuring behavior and verification
49
*/
50
expects(method: string): SinonExpectation;
51
52
/**
53
* Restore all mocked methods to their original implementations
54
*/
55
restore(): void;
56
57
/**
58
* Verify that all expectations on this mock have been satisfied
59
* @throws Error if any expectations are not met
60
*/
61
verify(): void;
62
}
63
```
64
65
**Usage Examples:**
66
67
```javascript
68
const api = {
69
fetch: (url) => Promise.resolve({}),
70
cache: (key, value) => {},
71
log: (message) => console.log(message)
72
};
73
74
const apiMock = sinon.mock(api);
75
76
// Set up expectations
77
apiMock.expects("fetch").once().withArgs("/users").returns(Promise.resolve({ users: [] }));
78
apiMock.expects("cache").twice();
79
apiMock.expects("log").never();
80
81
// Code under test would call api methods here
82
await api.fetch("/users");
83
api.cache("users", []);
84
api.cache("timestamp", Date.now());
85
86
// Verify all expectations were met
87
apiMock.verify(); // Passes if all expectations satisfied
88
apiMock.restore(); // Restore original methods
89
```
90
91
### Expectation Configuration
92
93
Configure individual method expectations with call counts and arguments.
94
95
```javascript { .api }
96
interface SinonExpectation {
97
/**
98
* Expect method to be called exactly once
99
* @returns The expectation for chaining
100
*/
101
once(): SinonExpectation;
102
103
/**
104
* Expect method to be called exactly twice
105
* @returns The expectation for chaining
106
*/
107
twice(): SinonExpectation;
108
109
/**
110
* Expect method to be called exactly three times
111
* @returns The expectation for chaining
112
*/
113
thrice(): SinonExpectation;
114
115
/**
116
* Expect method to be called an exact number of times
117
* @param count - Expected call count
118
* @returns The expectation for chaining
119
*/
120
exactly(count: number): SinonExpectation;
121
122
/**
123
* Expect method to be called at least a certain number of times
124
* @param count - Minimum expected call count
125
* @returns The expectation for chaining
126
*/
127
atLeast(count: number): SinonExpectation;
128
129
/**
130
* Expect method to be called at most a certain number of times
131
* @param count - Maximum expected call count
132
* @returns The expectation for chaining
133
*/
134
atMost(count: number): SinonExpectation;
135
136
/**
137
* Expect method to never be called
138
* @returns The expectation for chaining
139
*/
140
never(): SinonExpectation;
141
}
142
```
143
144
**Usage Examples:**
145
146
```javascript
147
const obj = { method: () => {} };
148
const mock = sinon.mock(obj);
149
150
// Exact call counts
151
mock.expects("method").once();
152
mock.expects("method").exactly(3);
153
154
// Range of call counts
155
mock.expects("method").atLeast(2);
156
mock.expects("method").atMost(5);
157
158
// Never called
159
mock.expects("method").never();
160
```
161
162
### Argument Expectations
163
164
Configure expectations for method arguments.
165
166
```javascript { .api }
167
interface SinonExpectation {
168
/**
169
* Expect method to be called with specific arguments (partial match)
170
* @param args - Expected arguments
171
* @returns The expectation for chaining
172
*/
173
withArgs(...args: any[]): SinonExpectation;
174
175
/**
176
* Expect method to be called with exact arguments (exact match)
177
* @param args - Expected exact arguments
178
* @returns The expectation for chaining
179
*/
180
withExactArgs(...args: any[]): SinonExpectation;
181
182
/**
183
* Expect method to be called with arguments matching patterns
184
* @param matchers - Matcher patterns for arguments
185
* @returns The expectation for chaining
186
*/
187
withMatch(...matchers: any[]): SinonExpectation;
188
}
189
```
190
191
**Usage Examples:**
192
193
```javascript
194
const obj = { process: (data, options) => {} };
195
const mock = sinon.mock(obj);
196
197
// Specific arguments
198
mock.expects("process").withArgs("test data", { format: "json" });
199
200
// Exact arguments (no additional args allowed)
201
mock.expects("process").withExactArgs("exact", "match");
202
203
// Matching patterns
204
import { match } from "sinon";
205
mock.expects("process").withMatch(match.string, match.object);
206
```
207
208
### Context Expectations
209
210
Configure expectations for method call context.
211
212
```javascript { .api }
213
interface SinonExpectation {
214
/**
215
* Expect method to be called with specific `this` context
216
* @param thisValue - Expected `this` value
217
* @returns The expectation for chaining
218
*/
219
on(thisValue: any): SinonExpectation;
220
}
221
```
222
223
**Usage Examples:**
224
225
```javascript
226
const context = { name: "test" };
227
const obj = { method: function() { return this.name; } };
228
const mock = sinon.mock(obj);
229
230
mock.expects("method").on(context);
231
232
// Call method with expected context
233
obj.method.call(context); // Satisfies expectation
234
```
235
236
### Behavior Configuration
237
238
Configure what the mocked method should do when called (same as stub behaviors).
239
240
```javascript { .api }
241
interface SinonExpectation {
242
/**
243
* Make expectation return a specific value
244
* @param value - Value to return
245
* @returns The expectation for chaining
246
*/
247
returns(value: any): SinonExpectation;
248
249
/**
250
* Make expectation return argument at specified index
251
* @param index - Argument index to return
252
* @returns The expectation for chaining
253
*/
254
returnsArg(index: number): SinonExpectation;
255
256
/**
257
* Make expectation return `this` context
258
* @returns The expectation for chaining
259
*/
260
returnsThis(): SinonExpectation;
261
262
/**
263
* Make expectation throw an exception
264
* @param error - Error to throw
265
* @returns The expectation for chaining
266
*/
267
throws(error?: any): SinonExpectation;
268
269
/**
270
* Make expectation throw exception with type and message
271
* @param type - Error type
272
* @param message - Error message
273
* @returns The expectation for chaining
274
*/
275
throws(type: string, message?: string): SinonExpectation;
276
277
/**
278
* Make expectation call a custom function
279
* @param func - Custom function to call
280
* @returns The expectation for chaining
281
*/
282
callsFake(func: Function): SinonExpectation;
283
284
/**
285
* Make expectation call the original method
286
* @returns The expectation for chaining
287
*/
288
callsThrough(): SinonExpectation;
289
290
/**
291
* Make expectation return resolved Promise
292
* @param value - Value to resolve with
293
* @returns The expectation for chaining
294
*/
295
resolves(value?: any): SinonExpectation;
296
297
/**
298
* Make expectation return rejected Promise
299
* @param error - Error to reject with
300
* @returns The expectation for chaining
301
*/
302
rejects(error?: any): SinonExpectation;
303
304
/**
305
* Make expectation call callback at specified index
306
* @param index - Callback argument index
307
* @returns The expectation for chaining
308
*/
309
callsArg(index: number): SinonExpectation;
310
311
/**
312
* Make expectation call callback with arguments
313
* @param index - Callback argument index
314
* @param args - Arguments for callback
315
* @returns The expectation for chaining
316
*/
317
callsArgWith(index: number, ...args: any[]): SinonExpectation;
318
319
/**
320
* Make expectation call first callback with arguments
321
* @param args - Arguments for callback
322
* @returns The expectation for chaining
323
*/
324
yields(...args: any[]): SinonExpectation;
325
}
326
```
327
328
**Usage Examples:**
329
330
```javascript
331
const obj = {
332
getValue: () => {},
333
processData: (data, callback) => {},
334
fetchUser: (id) => {}
335
};
336
const mock = sinon.mock(obj);
337
338
// Return value
339
mock.expects("getValue").returns(42);
340
341
// Throw exception
342
mock.expects("getValue").throws(new Error("Not found"));
343
344
// Promise behaviors
345
mock.expects("fetchUser").resolves({ id: 1, name: "John" });
346
347
// Callback behaviors
348
mock.expects("processData").yields(null, "processed");
349
350
// Custom implementation
351
mock.expects("getValue").callsFake(() => Date.now());
352
```
353
354
### Verification
355
356
Methods for verifying that expectations are met.
357
358
```javascript { .api }
359
interface SinonExpectation {
360
/**
361
* Verify that this individual expectation has been satisfied
362
* @throws Error if expectation is not met
363
*/
364
verify(): void;
365
}
366
367
interface SinonMock {
368
/**
369
* Verify all expectations on this mock
370
* @throws Error if any expectation is not met
371
*/
372
verify(): void;
373
}
374
```
375
376
**Usage Examples:**
377
378
```javascript
379
const obj = { method: () => {} };
380
const mock = sinon.mock(obj);
381
382
const expectation = mock.expects("method").once();
383
384
// Call the method
385
obj.method();
386
387
// Verify individual expectation
388
expectation.verify(); // Passes
389
390
// Or verify entire mock
391
mock.verify(); // Passes if all expectations satisfied
392
```
393
394
### Advanced Mock Patterns
395
396
Combining multiple expectations and complex verification scenarios.
397
398
**Usage Examples:**
399
400
```javascript
401
// Complex mock scenario
402
const database = {
403
connect: () => {},
404
query: (sql) => {},
405
disconnect: () => {}
406
};
407
408
const dbMock = sinon.mock(database);
409
410
// Set up call sequence expectations
411
dbMock.expects("connect").once().returns(true);
412
dbMock.expects("query")
413
.twice()
414
.withArgs(sinon.match.string)
415
.returns([{ id: 1 }]);
416
dbMock.expects("disconnect").once();
417
418
// Code under test
419
database.connect();
420
database.query("SELECT * FROM users");
421
database.query("SELECT * FROM posts");
422
database.disconnect();
423
424
// Verify all expectations
425
try {
426
dbMock.verify();
427
console.log("All database interactions verified");
428
} catch (error) {
429
console.error("Mock verification failed:", error.message);
430
} finally {
431
dbMock.restore();
432
}
433
```
434
435
```javascript
436
// Anonymous mock for callback testing
437
const onSuccess = sinon.mock("onSuccess").once().withArgs("result");
438
const onError = sinon.mock("onError").never();
439
440
// Code under test would call these
441
onSuccess("result"); // Satisfies expectation
442
443
try {
444
onSuccess.verify(); // Passes
445
onError.verify(); // Passes (never called as expected)
446
} catch (error) {
447
console.error("Callback expectations not met");
448
}
449
```
450
451
## Types
452
453
```javascript { .api }
454
interface SinonMock {
455
expects(method: string): SinonExpectation;
456
restore(): void;
457
verify(): void;
458
}
459
460
interface SinonExpectation {
461
// Call count expectations
462
once(): SinonExpectation;
463
twice(): SinonExpectation;
464
thrice(): SinonExpectation;
465
exactly(count: number): SinonExpectation;
466
atLeast(count: number): SinonExpectation;
467
atMost(count: number): SinonExpectation;
468
never(): SinonExpectation;
469
470
// Argument expectations
471
withArgs(...args: any[]): SinonExpectation;
472
withExactArgs(...args: any[]): SinonExpectation;
473
withMatch(...matchers: any[]): SinonExpectation;
474
475
// Context expectations
476
on(thisValue: any): SinonExpectation;
477
478
// Behavior configuration (extends stub behaviors)
479
returns(value: any): SinonExpectation;
480
throws(error?: any): SinonExpectation;
481
resolves(value?: any): SinonExpectation;
482
rejects(error?: any): SinonExpectation;
483
callsFake(func: Function): SinonExpectation;
484
callsThrough(): SinonExpectation;
485
yields(...args: any[]): SinonExpectation;
486
487
// Verification
488
verify(): void;
489
}
490
```