0
# Mock Integration
1
2
Global mocking system with automatic fallback for unresolved dependencies. This system integrates with popular mocking libraries to provide comprehensive test isolation and automatic mock generation for missing dependencies.
3
4
## Capabilities
5
6
### Mock Factory Integration
7
8
The TestingModuleBuilder supports global mock factories that automatically create mocks for unresolved dependencies.
9
10
```typescript { .api }
11
class TestingModuleBuilder {
12
/**
13
* Set a global mock factory for automatic dependency mocking
14
* @param mocker - Function that creates mocks based on injection tokens
15
* @returns TestingModuleBuilder for method chaining
16
*/
17
useMocker(mocker: MockFactory): TestingModuleBuilder;
18
}
19
20
/**
21
* Function type for creating mocks based on injection tokens
22
* @param token - The injection token for the dependency that needs mocking
23
* @returns Mock implementation for the dependency
24
*/
25
type MockFactory = (token?: InjectionToken) => any;
26
```
27
28
### Automatic Mock Resolution
29
30
The testing system automatically creates mocks for missing dependencies when a MockFactory is provided. When the dependency injection system cannot resolve a dependency, it falls back to using the mock factory to create a replacement.
31
32
**Usage Examples:**
33
34
```typescript
35
import { Test, TestingModule } from "@nestjs/testing";
36
import { createMock } from "@golevelup/ts-jest";
37
import { UsersService } from "./users.service";
38
import { DatabaseService } from "./database.service";
39
import { EmailService } from "./email.service";
40
41
describe("Mock Integration", () => {
42
let module: TestingModule;
43
44
beforeEach(async () => {
45
// Using @golevelup/ts-jest for automatic mocking
46
module = await Test.createTestingModule({
47
providers: [UsersService],
48
// Note: DatabaseService and EmailService are not provided
49
})
50
.useMocker(createMock)
51
.compile();
52
});
53
54
it("should automatically mock missing dependencies", async () => {
55
const usersService = module.get<UsersService>(UsersService);
56
57
// DatabaseService is automatically mocked
58
const result = await usersService.getUsers();
59
expect(result).toBeDefined();
60
});
61
});
62
```
63
64
### Custom Mock Factory
65
66
Create custom mock factories for specific testing needs:
67
68
```typescript
69
// Simple mock factory
70
const simpleMockFactory = (token: any): any => {
71
if (typeof token === "function") {
72
// For class constructors, create an object with mocked methods
73
const mockObj = {};
74
const prototype = token.prototype;
75
76
if (prototype) {
77
Object.getOwnPropertyNames(prototype).forEach((method) => {
78
if (method !== "constructor" && typeof prototype[method] === "function") {
79
mockObj[method] = jest.fn();
80
}
81
});
82
}
83
return mockObj;
84
}
85
86
// For tokens/strings, return a simple mock
87
return jest.fn();
88
};
89
90
// Advanced mock factory with type-aware mocking
91
const advancedMockFactory = (token: any): any => {
92
const tokenName = token?.name || token?.toString();
93
94
switch (tokenName) {
95
case "DatabaseService":
96
return {
97
findUser: jest.fn().mockResolvedValue({ id: 1, name: "Mock User" }),
98
saveUser: jest.fn().mockResolvedValue({ id: 1 }),
99
deleteUser: jest.fn().mockResolvedValue(true),
100
};
101
102
case "EmailService":
103
return {
104
sendEmail: jest.fn().mockResolvedValue({ sent: true, id: "mock-id" }),
105
validateEmail: jest.fn().mockReturnValue(true),
106
};
107
108
case "Logger":
109
return {
110
log: jest.fn(),
111
error: jest.fn(),
112
warn: jest.fn(),
113
debug: jest.fn(),
114
};
115
116
default:
117
// Fallback to generic mock
118
return createMock(token);
119
}
120
};
121
122
const moduleWithCustomMocking = await Test.createTestingModule({
123
providers: [ComplexService],
124
})
125
.useMocker(advancedMockFactory)
126
.compile();
127
```
128
129
### Integration with Popular Mocking Libraries
130
131
**Jest Auto-Mock:**
132
133
```typescript
134
import { Test } from "@nestjs/testing";
135
136
// Simple Jest-based mock factory
137
const jestMockFactory = (token: any) => {
138
if (typeof token === "function") {
139
const mockClass = jest.fn(() => ({}));
140
mockClass.prototype = Object.create(token.prototype);
141
return new mockClass();
142
}
143
return jest.fn();
144
};
145
146
const module = await Test.createTestingModule({
147
providers: [ServiceUnderTest],
148
})
149
.useMocker(jestMockFactory)
150
.compile();
151
```
152
153
**Sinon Integration:**
154
155
```typescript
156
import * as sinon from "sinon";
157
158
const sinonMockFactory = (token: any) => {
159
if (typeof token === "function") {
160
const mockObj = {};
161
const prototype = token.prototype;
162
163
Object.getOwnPropertyNames(prototype || {}).forEach((method) => {
164
if (method !== "constructor") {
165
mockObj[method] = sinon.stub();
166
}
167
});
168
169
return mockObj;
170
}
171
return sinon.stub();
172
};
173
174
const module = await Test.createTestingModule({
175
providers: [ServiceUnderTest],
176
})
177
.useMocker(sinonMockFactory)
178
.compile();
179
```
180
181
**ts-mockito Integration:**
182
183
```typescript
184
import { mock, instance } from "ts-mockito";
185
186
const tsMockitoFactory = (token: any) => {
187
if (typeof token === "function") {
188
const mockedClass = mock(token);
189
return instance(mockedClass);
190
}
191
return mock();
192
};
193
194
const module = await Test.createTestingModule({
195
providers: [ServiceUnderTest],
196
})
197
.useMocker(tsMockitoFactory)
198
.compile();
199
```
200
201
### Selective Mocking
202
203
Combine automatic mocking with specific overrides:
204
205
```typescript
206
const module = await Test.createTestingModule({
207
providers: [UsersService, EmailService], // EmailService is provided
208
})
209
.overrideProvider(EmailService)
210
.useValue({
211
sendEmail: jest.fn().mockResolvedValue({ sent: true }),
212
})
213
.useMocker(createMock) // Only mocks dependencies not explicitly provided/overridden
214
.compile();
215
216
// EmailService uses the explicit override
217
// Other missing dependencies use the mock factory
218
```
219
220
### Mock Factory Error Handling
221
222
Handle cases where mocking fails or dependencies can't be created:
223
224
```typescript
225
const safeMockFactory = (token: any): any => {
226
try {
227
// Attempt to create a specific mock
228
if (token?.name === "ProblematicService") {
229
return {
230
method1: jest.fn().mockRejectedValue(new Error("Service unavailable")),
231
method2: jest.fn().mockReturnValue(null),
232
};
233
}
234
235
// Default mocking logic
236
return createMock(token);
237
} catch (error) {
238
console.warn(`Failed to mock ${token?.name || token}:`, error.message);
239
240
// Return a minimal mock as fallback
241
return {
242
[Symbol.toStringTag]: `Mock<${token?.name || "Unknown"}>`,
243
};
244
}
245
};
246
247
const module = await Test.createTestingModule({
248
providers: [ServiceWithProblematicDependency],
249
})
250
.useMocker(safeMockFactory)
251
.compile();
252
```
253
254
### Testing with Partial Mocks
255
256
Create partial mocks that preserve some original functionality:
257
258
```typescript
259
import { UsersService } from "./users.service";
260
261
const partialMockFactory = (token: any): any => {
262
if (token === UsersService) {
263
const originalService = new UsersService({} as any);
264
265
return {
266
...originalService,
267
// Override specific methods
268
findUser: jest.fn().mockResolvedValue({ id: 1, name: "Test User" }),
269
// Keep other methods from original implementation
270
};
271
}
272
273
return createMock(token);
274
};
275
```
276
277
## Integration Patterns
278
279
### Async Mock Factories
280
281
```typescript
282
// Mock factory that handles async initialization
283
const asyncMockFactory = (token: any): any => {
284
const mockObj = createMock(token);
285
286
// Ensure async methods return promises
287
Object.keys(mockObj).forEach((key) => {
288
if (typeof mockObj[key] === "function") {
289
// Make all methods async-compatible
290
const originalMock = mockObj[key];
291
mockObj[key] = jest.fn().mockImplementation((...args) => {
292
const result = originalMock(...args);
293
return Promise.resolve(result);
294
});
295
}
296
});
297
298
return mockObj;
299
};
300
```
301
302
### Contextual Mocking
303
304
```typescript
305
// Context-aware mock factory
306
const contextualMockFactory = (token: any): any => {
307
const testName = expect.getState().currentTestName;
308
309
if (testName?.includes("error")) {
310
// Create error-throwing mocks for error tests
311
return createMock(token, {
312
throwError: true,
313
});
314
}
315
316
if (testName?.includes("empty")) {
317
// Create empty-result mocks
318
return createMock(token, {
319
returnEmpty: true,
320
});
321
}
322
323
return createMock(token);
324
};
325
```
326
327
## Types
328
329
```typescript { .api }
330
import { InjectionToken } from "@nestjs/common";
331
332
type MockFactory = (token?: InjectionToken) => any;
333
```