0
# Advanced Mock Generation
1
2
Low-level ModuleMocker class providing metadata-driven mock generation and advanced mocking scenarios for complex use cases.
3
4
## Capabilities
5
6
### ModuleMocker Class
7
8
Core class for advanced mock generation with full control over mock creation and management.
9
10
```typescript { .api }
11
/**
12
* Low-level mock generation class for advanced scenarios
13
*/
14
class ModuleMocker {
15
/**
16
* Creates a new ModuleMocker instance
17
* @param global - Global object of the environment (e.g., globalThis, window)
18
*/
19
constructor(global: typeof globalThis);
20
21
/**
22
* Creates a mock function with optional implementation
23
* @param implementation - Optional function implementation
24
* @returns Mock function with tracking capabilities
25
*/
26
fn<T extends FunctionLike = UnknownFunction>(implementation?: T): Mock<T>;
27
28
/**
29
* Creates a spy on an object method or property
30
* @param object - Target object
31
* @param methodKey - Method or property key to spy on
32
* @param accessType - For properties, specify 'get' or 'set'
33
* @returns MockInstance for the spied target
34
*/
35
spyOn<T extends object, K extends keyof T>(
36
object: T,
37
methodKey: K,
38
accessType?: 'get' | 'set'
39
): MockInstance;
40
41
/**
42
* Temporarily replaces an object property
43
* @param object - Target object
44
* @param propertyKey - Property key to replace
45
* @param value - New property value
46
* @returns Replaced instance with control methods
47
*/
48
replaceProperty<T extends object, K extends keyof T>(
49
object: T,
50
propertyKey: K,
51
value: T[K]
52
): Replaced<T[K]>;
53
54
/**
55
* Type assertion utility for mocked objects
56
* @param source - Object to assert as mocked
57
* @param options - Shallow or deep mocking options
58
* @returns Type-asserted mocked object
59
*/
60
mocked<T extends object>(source: T, options?: {shallow?: boolean}): Mocked<T> | MockedShallow<T>;
61
62
/**
63
* Checks if a function is a mock function
64
* @param fn - Function to check
65
* @returns True if function is a mock
66
*/
67
isMockFunction(fn: unknown): fn is Mock<UnknownFunction>;
68
69
/**
70
* Clears call history for all mocks created by this instance
71
*/
72
clearAllMocks(): void;
73
74
/**
75
* Resets all mocks created by this instance to default state
76
*/
77
resetAllMocks(): void;
78
79
/**
80
* Restores all spies created by this instance
81
*/
82
restoreAllMocks(): void;
83
}
84
85
type FunctionLike = (...args: any) => any;
86
type UnknownFunction = (...args: Array<unknown>) => unknown;
87
```
88
89
**Usage Examples:**
90
91
```typescript
92
import { ModuleMocker } from "jest-mock";
93
94
// Create a module mocker for specific environment
95
const mocker = new ModuleMocker(globalThis);
96
97
// Create mock functions
98
const mockFn = mocker.fn((x: number) => x * 2);
99
console.log(mockFn(5)); // 10
100
101
// Create spies
102
const obj = { method: () => 'original' };
103
const spy = mocker.spyOn(obj, 'method');
104
spy.mockReturnValue('mocked');
105
106
// Bulk operations
107
mocker.clearAllMocks();
108
mocker.restoreAllMocks();
109
```
110
111
### Metadata-Driven Mock Generation
112
113
Generate mocks from metadata schemas describing object structure and behavior.
114
115
```typescript { .api }
116
/**
117
* Generates a mock from metadata schema
118
* @param metadata - Object metadata in schema format
119
* @returns Generated mock object
120
*/
121
generateFromMetadata<T>(metadata: MockMetadata<T>): Mocked<T>;
122
123
/**
124
* Extracts metadata schema from existing object
125
* @param component - Object to analyze
126
* @param _refs - Internal reference tracking (optional)
127
* @returns Metadata schema or null if not mockable
128
*/
129
getMetadata<T = unknown>(component: T, _refs?: Map<T, number>): MockMetadata<T> | null;
130
131
/**
132
* Metadata schema format for mock generation
133
*/
134
interface MockMetadata<T, MetadataType = MockMetadataType> {
135
/** Reference ID for circular references */
136
ref?: number;
137
/** Nested object member metadata */
138
members?: Record<string, MockMetadata<T>>;
139
/** Mock implementation for functions */
140
mockImpl?: T;
141
/** Function name */
142
name?: string;
143
/** Unique reference identifier */
144
refID?: number;
145
/** Type of the metadata */
146
type?: MetadataType;
147
/** Constant value */
148
value?: T;
149
/** Function arity (parameter count) */
150
length?: number;
151
}
152
153
type MockMetadataType =
154
| 'object'
155
| 'array'
156
| 'regexp'
157
| 'function'
158
| 'constant'
159
| 'collection'
160
| 'null'
161
| 'undefined';
162
```
163
164
**Usage Examples:**
165
166
```typescript
167
import { ModuleMocker } from "jest-mock";
168
169
const mocker = new ModuleMocker(globalThis);
170
171
// Extract metadata from existing object
172
const originalObject = {
173
name: 'example',
174
calculate: (a: number, b: number) => a + b,
175
nested: {
176
value: 42,
177
transform: (x: number) => x * 2
178
}
179
};
180
181
const metadata = mocker.getMetadata(originalObject);
182
console.log(metadata?.type); // 'object'
183
console.log(metadata?.members?.calculate?.type); // 'function'
184
185
// Generate mock from metadata
186
const mockObject = mocker.generateFromMetadata(metadata!);
187
console.log(mocker.isMockFunction(mockObject.calculate)); // true
188
console.log(mocker.isMockFunction(mockObject.nested.transform)); // true
189
190
// Use generated mocks
191
mockObject.calculate.mockReturnValue(100);
192
console.log(mockObject.calculate(1, 2)); // 100
193
```
194
195
### Manual Metadata Creation
196
197
Create metadata schemas manually for custom mock generation.
198
199
```typescript { .api }
200
// Create metadata for a function
201
const functionMetadata: MockMetadata<(x: number) => string> = {
202
type: 'function',
203
name: 'myFunction',
204
length: 1
205
};
206
207
// Create metadata for an object with methods
208
const objectMetadata: MockMetadata<any> = {
209
type: 'object',
210
members: {
211
method1: {
212
type: 'function',
213
name: 'method1',
214
length: 2
215
},
216
property1: {
217
type: 'constant',
218
value: 'test'
219
},
220
nested: {
221
type: 'object',
222
members: {
223
innerMethod: {
224
type: 'function',
225
name: 'innerMethod'
226
}
227
}
228
}
229
}
230
};
231
232
const mock = mocker.generateFromMetadata(objectMetadata);
233
// mock.method1 is a mock function
234
// mock.property1 is 'test'
235
// mock.nested.innerMethod is a mock function
236
```
237
238
### Circular Reference Handling
239
240
Handle objects with circular references using ref/refID system.
241
242
```typescript { .api }
243
// Metadata with circular reference
244
const circularMetadata: MockMetadata<any> = {
245
type: 'object',
246
refID: 1,
247
members: {
248
name: {
249
type: 'constant',
250
value: 'circular'
251
},
252
self: {
253
ref: 1 // References the object with refID: 1
254
}
255
}
256
};
257
258
const circularMock = mocker.generateFromMetadata(circularMetadata);
259
console.log(circularMock.self === circularMock); // true
260
```
261
262
### Mock Detection and Management
263
264
Utilities for detecting and managing mock functions.
265
266
```typescript { .api }
267
/**
268
* Type guard to check if a value is a mock function
269
* @param fn - Value to check
270
* @returns True if value is a mock function
271
*/
272
isMockFunction<T extends FunctionLike = UnknownFunction>(fn: MockInstance<T>): fn is MockInstance<T>;
273
isMockFunction<P extends Array<unknown>, R>(fn: (...args: P) => R): fn is Mock<(...args: P) => R>;
274
isMockFunction(fn: unknown): fn is Mock<UnknownFunction>;
275
276
/**
277
* Clears call history for all mocks created by this ModuleMocker
278
*/
279
clearAllMocks(): void;
280
281
/**
282
* Resets all mocks created by this ModuleMocker to default state
283
*/
284
resetAllMocks(): void;
285
286
/**
287
* Restores all spies created by this ModuleMocker
288
*/
289
restoreAllMocks(): void;
290
```
291
292
**Usage Examples:**
293
294
```typescript
295
import { ModuleMocker } from "jest-mock";
296
297
const mocker = new ModuleMocker(globalThis);
298
299
// Create various mocks
300
const fn1 = mocker.fn();
301
const fn2 = mocker.fn();
302
const obj = { method: () => 'original' };
303
const spy = mocker.spyOn(obj, 'method');
304
305
// Check if functions are mocks
306
console.log(mocker.isMockFunction(fn1)); // true
307
console.log(mocker.isMockFunction(obj.method)); // true (after spying)
308
console.log(mocker.isMockFunction(() => {})); // false
309
310
// Call mocks to create history
311
fn1('test');
312
fn2(1, 2, 3);
313
obj.method();
314
315
// Bulk operations
316
mocker.clearAllMocks(); // Clears call history but preserves implementations
317
console.log(fn1.mock.calls.length); // 0
318
319
mocker.resetAllMocks(); // Clears history AND implementations
320
console.log(fn1()); // undefined (implementation cleared)
321
322
mocker.restoreAllMocks(); // Restores original implementations for spies
323
console.log(obj.method()); // 'original' (restored)
324
```
325
326
### Environment-Specific Mocking
327
328
Create mocks for different JavaScript environments.
329
330
```typescript { .api }
331
// Browser environment
332
const browserMocker = new ModuleMocker(window);
333
334
// Node.js environment
335
const nodeMocker = new ModuleMocker(globalThis);
336
337
// Custom environment
338
const customGlobal = {
339
Object: Object,
340
Function: Function,
341
Array: Array,
342
RegExp: RegExp,
343
Promise: Promise
344
};
345
const customMocker = new ModuleMocker(customGlobal as any);
346
```
347
348
## Advanced Usage Patterns
349
350
### Mock Factory Pattern
351
352
```typescript
353
import { ModuleMocker } from "jest-mock";
354
355
class MockFactory {
356
private mocker = new ModuleMocker(globalThis);
357
358
createMockService<T extends object>(Service: new () => T): T {
359
const instance = new Service();
360
const metadata = this.mocker.getMetadata(instance);
361
return this.mocker.generateFromMetadata(metadata!) as T;
362
}
363
364
cleanup() {
365
this.mocker.restoreAllMocks();
366
this.mocker.clearAllMocks();
367
}
368
}
369
370
// Usage
371
const factory = new MockFactory();
372
const mockService = factory.createMockService(MyService);
373
// All methods of MyService are now mocked
374
```
375
376
### Metadata Transformation
377
378
```typescript
379
import { ModuleMocker, MockMetadata } from "jest-mock";
380
381
function addMockImplementation<T>(
382
metadata: MockMetadata<T>,
383
implementations: Record<string, Function>
384
): MockMetadata<T> {
385
if (metadata.members) {
386
for (const [key, member] of Object.entries(metadata.members)) {
387
if (member.type === 'function' && implementations[key]) {
388
member.mockImpl = implementations[key] as any;
389
}
390
}
391
}
392
return metadata;
393
}
394
395
// Usage
396
const mocker = new ModuleMocker(globalThis);
397
let metadata = mocker.getMetadata(originalObject);
398
metadata = addMockImplementation(metadata!, {
399
calculate: (a: number, b: number) => a * b // Override addition with multiplication
400
});
401
const mock = mocker.generateFromMetadata(metadata);
402
```
403
404
## Types
405
406
```typescript { .api }
407
interface Mock<T extends FunctionLike = UnknownFunction> extends Function, MockInstance<T> {
408
new (...args: Parameters<T>): ReturnType<T>;
409
(...args: Parameters<T>): ReturnType<T>;
410
}
411
412
interface Replaced<T = unknown> {
413
restore(): void;
414
replaceValue(value: T): this;
415
}
416
417
type Mocked<T> = T extends ClassLike
418
? MockedClass<T>
419
: T extends FunctionLike
420
? MockedFunction<T>
421
: T extends object
422
? MockedObject<T>
423
: T;
424
425
type MockedShallow<T> = T extends ClassLike
426
? MockedClass<T>
427
: T extends FunctionLike
428
? MockedFunctionShallow<T>
429
: T extends object
430
? MockedObjectShallow<T>
431
: T;
432
```