0
# Mocking Support
1
2
QuarkusMock provides runtime mock installation for CDI normal scoped beans, enabling test isolation and controlled behavior during testing.
3
4
## QuarkusMock Class
5
6
Utility class for installing mocks for CDI normal scoped beans including `@ApplicationScoped` and `@RequestScoped` beans.
7
8
```java { .api }
9
public class QuarkusMock {
10
11
/**
12
* Installs a mock for a CDI normal scoped bean
13
*
14
* @param mock The mock object
15
* @param instance The CDI normal scoped bean that was injected into your test
16
* @param <T> The bean type
17
*/
18
public static <T> void installMockForInstance(T mock, T instance);
19
20
/**
21
* Installs a mock for a CDI normal scoped bean
22
*
23
* @param mock The mock object
24
* @param instance The type of the CDI normal scoped bean to replace
25
* @param qualifiers The CDI qualifiers of the bean to mock
26
* @param <T> The bean type
27
*/
28
public static <T> void installMockForType(T mock, Class<? super T> instance, Annotation... qualifiers);
29
30
/**
31
* Installs a mock for a CDI normal scoped bean by typeLiteral and qualifiers
32
*
33
* @param mock The mock object
34
* @param typeLiteral TypeLiteral representing the required type
35
* @param qualifiers The CDI qualifiers of the bean to mock
36
* @param <T> The bean type
37
*/
38
public static <T> void installMockForType(T mock, TypeLiteral<? super T> typeLiteral, Annotation... qualifiers);
39
}
40
```
41
42
## Basic Mock Installation
43
44
### Mock by Instance
45
46
```java
47
import io.quarkus.test.junit.QuarkusTest;
48
import io.quarkus.test.junit.QuarkusMock;
49
import jakarta.inject.Inject;
50
import org.junit.jupiter.api.BeforeEach;
51
import org.junit.jupiter.api.Test;
52
import org.mockito.Mockito;
53
54
@QuarkusTest
55
class UserServiceTest {
56
57
@Inject
58
UserService userService;
59
60
@Inject
61
EmailService emailService; // Real CDI bean injected
62
63
@BeforeEach
64
void setup() {
65
// Create mock and install it for the injected instance
66
EmailService mockEmailService = Mockito.mock(EmailService.class);
67
QuarkusMock.installMockForInstance(mockEmailService, emailService);
68
69
// Configure mock behavior
70
Mockito.when(mockEmailService.sendWelcomeEmail(Mockito.anyString()))
71
.thenReturn(true);
72
}
73
74
@Test
75
void testUserRegistration() {
76
User user = userService.registerUser("john@example.com", "password");
77
78
// Verify mock was called
79
Mockito.verify(emailService).sendWelcomeEmail("john@example.com");
80
assertNotNull(user);
81
}
82
}
83
```
84
85
### Mock by Type
86
87
```java
88
import io.quarkus.test.junit.QuarkusTest;
89
import io.quarkus.test.junit.QuarkusMock;
90
import org.junit.jupiter.api.BeforeEach;
91
import org.junit.jupiter.api.Test;
92
import org.mockito.Mockito;
93
94
@QuarkusTest
95
class PaymentProcessorTest {
96
97
@BeforeEach
98
void setup() {
99
// Mock by type without needing injection
100
PaymentGateway mockGateway = Mockito.mock(PaymentGateway.class);
101
QuarkusMock.installMockForType(mockGateway, PaymentGateway.class);
102
103
Mockito.when(mockGateway.processPayment(Mockito.any()))
104
.thenReturn(new PaymentResult(true, "SUCCESS"));
105
}
106
107
@Test
108
void testPaymentProcessing() {
109
// Test logic that uses PaymentGateway
110
}
111
}
112
```
113
114
## Advanced Mocking Patterns
115
116
### Qualified Bean Mocking
117
118
```java
119
@ApplicationScoped
120
@Named("primary")
121
public class PrimaryEmailService implements EmailService { }
122
123
@ApplicationScoped
124
@Named("backup")
125
public class BackupEmailService implements EmailService { }
126
127
@QuarkusTest
128
class QualifiedMockTest {
129
130
@BeforeEach
131
void setup() {
132
EmailService mockPrimary = Mockito.mock(EmailService.class);
133
EmailService mockBackup = Mockito.mock(EmailService.class);
134
135
// Mock qualified beans
136
QuarkusMock.installMockForType(mockPrimary, EmailService.class,
137
NamedLiteral.of("primary"));
138
QuarkusMock.installMockForType(mockBackup, EmailService.class,
139
NamedLiteral.of("backup"));
140
}
141
}
142
```
143
144
### Generic Type Mocking
145
146
```java
147
@ApplicationScoped
148
public class GenericRepository<T> {
149
public List<T> findAll() { return List.of(); }
150
}
151
152
@QuarkusTest
153
class GenericMockTest {
154
155
@BeforeEach
156
void setup() {
157
@SuppressWarnings("unchecked")
158
GenericRepository<User> mockRepo = Mockito.mock(GenericRepository.class);
159
160
// Mock using TypeLiteral for generic types
161
TypeLiteral<GenericRepository<User>> typeLiteral =
162
new TypeLiteral<GenericRepository<User>>() {};
163
164
QuarkusMock.installMockForType(mockRepo, typeLiteral);
165
166
Mockito.when(mockRepo.findAll())
167
.thenReturn(List.of(new User("test")));
168
}
169
}
170
```
171
172
### Mock Lifecycle Management
173
174
```java
175
@QuarkusTest
176
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
177
class MockLifecycleTest {
178
179
private EmailService globalMock;
180
181
@BeforeAll
182
void setupGlobalMock() {
183
// Global mocks persist across all tests
184
globalMock = Mockito.mock(EmailService.class);
185
QuarkusMock.installMockForType(globalMock, EmailService.class);
186
}
187
188
@BeforeEach
189
void setupPerTestMock() {
190
// Per-test mocks are cleared after each test
191
NotificationService perTestMock = Mockito.mock(NotificationService.class);
192
QuarkusMock.installMockForType(perTestMock, NotificationService.class);
193
}
194
195
@Test
196
void testWithBothMocks() {
197
// Both global and per-test mocks are active
198
}
199
}
200
```
201
202
## Mock Configuration Patterns
203
204
### Stubbing and Verification
205
206
```java
207
@QuarkusTest
208
class PaymentServiceTest {
209
210
@Inject
211
PaymentService paymentService;
212
213
@Inject
214
AuditService auditService;
215
216
@BeforeEach
217
void setup() {
218
AuditService mockAudit = Mockito.mock(AuditService.class);
219
QuarkusMock.installMockForInstance(mockAudit, auditService);
220
221
// Stub void methods
222
Mockito.doNothing().when(mockAudit).logPayment(Mockito.any());
223
224
// Stub methods with return values
225
Mockito.when(mockAudit.isAuditEnabled()).thenReturn(true);
226
}
227
228
@Test
229
void testPaymentWithAudit() {
230
paymentService.processPayment(new Payment(100.0));
231
232
// Verify interactions
233
Mockito.verify(auditService).logPayment(Mockito.any(Payment.class));
234
Mockito.verify(auditService, Mockito.times(1)).isAuditEnabled();
235
}
236
}
237
```
238
239
### Exception Simulation
240
241
```java
242
@QuarkusTest
243
class ErrorHandlingTest {
244
245
@BeforeEach
246
void setup() {
247
DatabaseService mockDb = Mockito.mock(DatabaseService.class);
248
QuarkusMock.installMockForType(mockDb, DatabaseService.class);
249
250
// Simulate database connection failure
251
Mockito.when(mockDb.save(Mockito.any()))
252
.thenThrow(new DatabaseException("Connection failed"));
253
}
254
255
@Test
256
void testDatabaseErrorHandling() {
257
assertThrows(ServiceException.class, () -> {
258
userService.createUser("test@example.com");
259
});
260
}
261
}
262
```
263
264
### Complex Mock Scenarios
265
266
```java
267
@QuarkusTest
268
class ComplexMockingTest {
269
270
@BeforeEach
271
void setupComplexMocks() {
272
// Mock with conditional responses
273
ExternalApiService mockApi = Mockito.mock(ExternalApiService.class);
274
275
Mockito.when(mockApi.getUserData("valid-id"))
276
.thenReturn(new UserData("John Doe"));
277
Mockito.when(mockApi.getUserData("invalid-id"))
278
.thenThrow(new ApiException("User not found"));
279
280
QuarkusMock.installMockForType(mockApi, ExternalApiService.class);
281
282
// Mock with sequential responses
283
CacheService mockCache = Mockito.mock(CacheService.class);
284
Mockito.when(mockCache.get("key"))
285
.thenReturn(null) // First call: cache miss
286
.thenReturn("cached-value"); // Second call: cache hit
287
288
QuarkusMock.installMockForType(mockCache, CacheService.class);
289
}
290
}
291
```
292
293
## Integration with Test Profiles
294
295
```java
296
// Test profile that provides mock configuration
297
public class MockedServicesProfile implements QuarkusTestProfile {
298
299
@Override
300
public Set<Class<?>> getEnabledAlternatives() {
301
return Set.of(MockEmailService.class, MockPaymentGateway.class);
302
}
303
304
@Override
305
public Map<String, String> getConfigOverrides() {
306
return Map.of(
307
"external.api.enabled", "false",
308
"cache.enabled", "false"
309
);
310
}
311
}
312
313
@QuarkusTest
314
@TestProfile(MockedServicesProfile.class)
315
class IntegratedMockTest {
316
317
@BeforeEach
318
void setupRuntimeMocks() {
319
// Combine profile alternatives with runtime mocks
320
DatabaseService mockDb = Mockito.mock(DatabaseService.class);
321
QuarkusMock.installMockForType(mockDb, DatabaseService.class);
322
}
323
}
324
```
325
326
## Best Practices and Limitations
327
328
### Supported Bean Scopes
329
- ✅ `@ApplicationScoped` - Fully supported
330
- ✅ `@RequestScoped` - Fully supported
331
- ❌ `@Singleton` - Not supported (not a normal scoped bean)
332
- ❌ `@Dependent` - Not supported (not a normal scoped bean)
333
334
### Thread Safety Considerations
335
```java
336
@QuarkusTest
337
class ThreadSafetyTest {
338
339
@Test
340
void testConcurrentAccess() {
341
// Note: Mocks are global, so concurrent test execution
342
// can cause race conditions. Avoid parallel execution
343
// when using QuarkusMock.
344
}
345
}
346
```
347
348
### Mock Cleanup
349
```java
350
@QuarkusTest
351
class MockCleanupTest {
352
353
@Test
354
void testOne() {
355
// Install mock for this test
356
Service mock = Mockito.mock(Service.class);
357
QuarkusMock.installMockForType(mock, Service.class);
358
359
// Mock is automatically cleared after test
360
}
361
362
@Test
363
void testTwo() {
364
// Fresh application context without previous test's mock
365
}
366
}
367
```
368
369
### Error Scenarios
370
371
```java
372
// This will throw RuntimeException
373
Service invalidMock = new Service() { /* implementation */ };
374
QuarkusMock.installMockForType(invalidMock, WrongType.class);
375
// Error: invalidMock is not assignable to WrongType
376
```