0
# Core Test Annotations
1
2
Essential annotations for mocking, transaction management, and session context control in Quarkus tests. These annotations provide declarative control over test behavior and automatically integrate with the Quarkus testing framework.
3
4
## Capabilities
5
6
### Mock Annotation
7
8
Built-in stereotype for creating mock beans in the CDI container during test execution.
9
10
```java { .api }
11
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
12
@Retention(RetentionPolicy.RUNTIME)
13
@Stereotype
14
public @interface Mock {}
15
```
16
17
**Usage Example:**
18
```java
19
public interface UserService {
20
User findById(Long id);
21
User save(User user);
22
}
23
24
@Mock
25
@ApplicationScoped
26
public class MockUserService implements UserService {
27
@Override
28
public User findById(Long id) {
29
return new User(id, "Mock User", "mock@example.com");
30
}
31
32
@Override
33
public User save(User user) {
34
user.setId(99L);
35
return user;
36
}
37
}
38
39
public class UserControllerTest {
40
@Inject
41
UserService userService; // Automatically receives MockUserService
42
43
@Test
44
public void testMockService() {
45
User user = userService.findById(1L);
46
assertEquals("Mock User", user.getName());
47
}
48
}
49
```
50
51
### InjectMock Annotation
52
53
Instructs the test engine to inject mock instances, typically used with mocking frameworks like Mockito.
54
55
```java { .api }
56
@Target({ElementType.FIELD, ElementType.PARAMETER})
57
@Retention(RetentionPolicy.RUNTIME)
58
public @interface InjectMock {}
59
```
60
61
**Usage with Mockito:**
62
```java
63
public class OrderServiceTest {
64
@InjectMock
65
PaymentService paymentService;
66
67
@InjectMock
68
InventoryService inventoryService;
69
70
@Inject
71
OrderService orderService; // Real service with mocked dependencies
72
73
@Test
74
public void testOrderProcessing() {
75
// Setup mocks
76
when(inventoryService.isAvailable("ITEM_001")).thenReturn(true);
77
when(paymentService.processPayment(any())).thenReturn(true);
78
79
// Test with mocked dependencies
80
Order order = new Order("ITEM_001", 2);
81
OrderResult result = orderService.processOrder(order);
82
83
assertTrue(result.isSuccess());
84
verify(paymentService).processPayment(any());
85
verify(inventoryService).isAvailable("ITEM_001");
86
}
87
}
88
```
89
90
### TestTransaction Annotation
91
92
Runs the annotated method in a rollback-only JTA transaction, ensuring database changes are automatically reverted.
93
94
```java { .api }
95
@Target({ElementType.METHOD})
96
@Retention(RetentionPolicy.RUNTIME)
97
@InterceptorBinding
98
public @interface TestTransaction {}
99
```
100
101
**Usage Example:**
102
```java
103
public class UserRepositoryTest {
104
@Inject
105
UserRepository userRepository;
106
107
@Test
108
@TestTransaction
109
public void testUserCreation() {
110
// Any database changes are automatically rolled back
111
User user = new User("Alice", "alice@example.com");
112
userRepository.persist(user);
113
114
assertNotNull(user.getId());
115
116
// Verify user exists within transaction
117
User found = userRepository.findById(user.getId());
118
assertEquals("Alice", found.getName());
119
120
// Changes will be rolled back after method completes
121
}
122
123
@Test
124
public void testUserDoesNotExist() {
125
// User from previous test was rolled back
126
List<User> users = userRepository.listAll();
127
assertTrue(users.isEmpty());
128
}
129
}
130
```
131
132
### TestReactiveTransaction Annotation
133
134
Runs the annotated method in a rollback-only reactive transaction for reactive data access.
135
136
```java { .api }
137
@Target({ElementType.METHOD})
138
@Retention(RetentionPolicy.RUNTIME)
139
@InterceptorBinding
140
public @interface TestReactiveTransaction {}
141
```
142
143
**Usage with Reactive Panache:**
144
```java
145
public class ReactiveUserRepositoryTest {
146
@Test
147
@TestReactiveTransaction
148
public Uni<Void> testReactiveUserCreation() {
149
User user = new User("Bob", "bob@example.com");
150
151
return user.persist()
152
.chain(ignored -> {
153
assertNotNull(user.getId());
154
return User.findById(user.getId());
155
})
156
.invoke(found -> {
157
assertEquals("Bob", found.getName());
158
// Transaction will be rolled back
159
})
160
.replaceWithVoid();
161
}
162
}
163
```
164
165
### ActivateSessionContext Annotation
166
167
Activates the HTTP session context before method execution, useful for testing session-scoped beans.
168
169
```java { .api }
170
@Target({ElementType.METHOD})
171
@Retention(RetentionPolicy.RUNTIME)
172
@InterceptorBinding
173
public @interface ActivateSessionContext {}
174
```
175
176
**Usage Example:**
177
```java
178
@SessionScoped
179
public class ShoppingCart implements Serializable {
180
private List<Item> items = new ArrayList<>();
181
182
public void addItem(Item item) {
183
items.add(item);
184
}
185
186
public List<Item> getItems() {
187
return items;
188
}
189
}
190
191
public class ShoppingCartTest {
192
@Inject
193
ShoppingCart cart;
194
195
@Test
196
@ActivateSessionContext
197
public void testSessionScopedCart() {
198
// Session context is automatically activated
199
cart.addItem(new Item("Book", 29.99));
200
cart.addItem(new Item("Pen", 1.99));
201
202
assertEquals(2, cart.getItems().size());
203
assertEquals(31.98, cart.getItems().stream()
204
.mapToDouble(Item::getPrice).sum(), 0.01);
205
}
206
}
207
```
208
209
### TestMethodInvoker Interface
210
211
SPI for altering test method invocation, allowing custom parameter injection and method execution control.
212
213
```java { .api }
214
public interface TestMethodInvoker {
215
boolean handlesMethodParamType(String paramClassName);
216
Object methodParamInstance(String paramClassName);
217
boolean supportsMethod(Class<?> originalTestClass, Method originalTestMethod);
218
Object invoke(Object actualTestInstance, Method actualTestMethod,
219
List<Object> actualTestMethodArgs, String testClassName) throws Throwable;
220
}
221
```
222
223
**Custom Test Method Invoker:**
224
```java
225
public class CustomParameterInvoker implements TestMethodInvoker {
226
@Override
227
public boolean handlesMethodParamType(String paramClassName) {
228
return "com.example.TestContext".equals(paramClassName);
229
}
230
231
@Override
232
public Object methodParamInstance(String paramClassName) {
233
if ("com.example.TestContext".equals(paramClassName)) {
234
return new TestContext("test-environment");
235
}
236
return null;
237
}
238
239
@Override
240
public boolean supportsMethod(Class<?> originalTestClass, Method originalTestMethod) {
241
return Arrays.stream(originalTestMethod.getParameterTypes())
242
.anyMatch(type -> type.getName().equals("com.example.TestContext"));
243
}
244
245
@Override
246
public Object invoke(Object actualTestInstance, Method actualTestMethod,
247
List<Object> actualTestMethodArgs, String testClassName) throws Throwable {
248
// Custom method invocation logic
249
System.out.println("Invoking test with custom context: " + testClassName);
250
return actualTestMethod.invoke(actualTestInstance, actualTestMethodArgs.toArray());
251
}
252
}
253
254
// Usage in test:
255
public class CustomParameterTest {
256
@Test
257
public void testWithCustomParameter(TestContext context) {
258
// TestContext is automatically injected by CustomParameterInvoker
259
assertEquals("test-environment", context.getEnvironment());
260
}
261
}
262
```
263
264
## Advanced Usage Patterns
265
266
### Combining Annotations
267
268
Multiple annotations can be combined for comprehensive test setup:
269
270
```java
271
public class ComprehensiveTest {
272
@InjectMock
273
ExternalService externalService;
274
275
@Test
276
@TestTransaction
277
@ActivateSessionContext
278
public void testWithMultipleContexts(TestContext context) {
279
// Setup mocks
280
when(externalService.getData()).thenReturn("mock-data");
281
282
// Test logic with transaction, session, and custom parameter
283
// All contexts are properly activated and cleaned up
284
}
285
}
286
```
287
288
### Mock Alternatives and Spies
289
290
Using different mocking strategies:
291
292
```java
293
public class AdvancedMockingTest {
294
@InjectMock
295
UserService userService;
296
297
@Test
298
public void testWithSpy() {
299
// Convert mock to spy for partial mocking
300
UserService spy = Mockito.spy(userService);
301
doReturn(true).when(spy).isValidUser(any());
302
// Call real methods for other operations
303
}
304
305
@Test
306
public void testWithAnswer() {
307
when(userService.findById(any())).thenAnswer(invocation -> {
308
Long id = invocation.getArgument(0);
309
return new User(id, "User " + id, id + "@example.com");
310
});
311
312
User user1 = userService.findById(1L);
313
User user2 = userService.findById(2L);
314
315
assertEquals("User 1", user1.getName());
316
assertEquals("User 2", user2.getName());
317
}
318
}
319
```
320
321
### Transaction Isolation Testing
322
323
Testing different transaction scenarios:
324
325
```java
326
public class TransactionTest {
327
@Inject
328
UserRepository userRepository;
329
330
@Test
331
@TestTransaction
332
public void testTransactionalBehavior() {
333
User user = new User("Charlie", "charlie@example.com");
334
userRepository.persist(user);
335
336
// Within transaction, user exists
337
assertTrue(userRepository.isPersistent(user));
338
339
// But will be rolled back after test
340
}
341
342
@Test
343
public void testNonTransactionalBehavior() {
344
// No @TestTransaction - changes persist
345
User user = new User("David", "david@example.com");
346
userRepository.persist(user);
347
348
// Need manual cleanup in @AfterEach
349
}
350
351
@AfterEach
352
public void cleanup() {
353
// Manual cleanup for non-transactional tests
354
userRepository.deleteAll();
355
}
356
}
357
```