0
# Mock Integration
1
2
Seamless Mockito integration with Spring context for mocking beans and services in Spring Boot tests.
3
4
> **⚠️ Deprecation Notice**: As of Spring Boot 3.4.0, `@MockBean` and `@SpyBean` are deprecated for removal. Use `@MockitoBean` and `@MockitoSpyBean` from Spring Framework 6.2+ instead:
5
> - `org.springframework.test.context.bean.override.mockito.MockitoBean`
6
> - `org.springframework.test.context.bean.override.mockito.MockitoSpyBean`
7
8
## Capabilities
9
10
### @MockBean Annotation
11
12
Creates and injects Mockito mocks into the Spring application context.
13
14
```java { .api }
15
/**
16
* Annotation that can be used to add mocks to a Spring ApplicationContext
17
* @since 1.4.0
18
* @deprecated since 3.4.0 for removal in Spring Boot 4.0.0. Use {@code @MockitoBean} from Spring Framework instead.
19
*/
20
@SuppressWarnings("removal")
21
@Deprecated(since = "3.4.0", forRemoval = true)
22
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
23
@Retention(RetentionPolicy.RUNTIME)
24
@Documented
25
@Repeatable(MockBeans.class)
26
public @interface MockBean {
27
/**
28
* The name of the bean to register or replace
29
*/
30
String name() default "";
31
32
/**
33
* The classes to mock
34
*/
35
Class<?>[] classes() default {};
36
37
/**
38
* Extra interfaces that should also be declared on the mock
39
*/
40
Class<?>[] extraInterfaces() default {};
41
42
/**
43
* The Mockito Answer to use on the mock
44
*/
45
Answers answer() default Answers.RETURNS_DEFAULTS;
46
47
/**
48
* Whether the mock is serializable
49
*/
50
boolean serializable() default false;
51
52
/**
53
* When to reset the mock
54
*/
55
MockReset reset() default MockReset.AFTER;
56
}
57
58
/**
59
* Container annotation for @MockBean
60
* @deprecated since 3.4.0 for removal in Spring Boot 4.0.0. Use {@code @MockitoBean} from Spring Framework instead.
61
*/
62
@SuppressWarnings("removal")
63
@Deprecated(since = "3.4.0", forRemoval = true)
64
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
65
@Retention(RetentionPolicy.RUNTIME)
66
@Documented
67
public @interface MockBeans {
68
MockBean[] value();
69
}
70
```
71
72
**Usage Examples:**
73
74
```java
75
@SpringBootTest
76
class MockBeanTest {
77
78
@MockBean
79
private UserService userService;
80
81
@MockBean
82
private EmailService emailService;
83
84
@Autowired
85
private UserController userController;
86
87
@Test
88
void mockBeanIsInjected() {
89
// Mock behavior
90
User mockUser = new User("test@example.com", "Test User");
91
when(userService.findByEmail("test@example.com")).thenReturn(mockUser);
92
93
// Test controller using mocked service
94
ResponseEntity<User> response = userController.getUser("test@example.com");
95
96
assertThat(response.getBody()).isEqualTo(mockUser);
97
verify(userService).findByEmail("test@example.com");
98
}
99
100
@Test
101
void mockWithCustomAnswer() {
102
// Configure mock with custom answer
103
when(userService.findByEmail(anyString()))
104
.thenAnswer(invocation -> {
105
String email = invocation.getArgument(0);
106
return new User(email, "Generated User");
107
});
108
109
User user = userService.findByEmail("any@example.com");
110
assertThat(user.getEmail()).isEqualTo("any@example.com");
111
assertThat(user.getName()).isEqualTo("Generated User");
112
}
113
}
114
115
// Multiple mocks with container annotation
116
@MockBeans({
117
@MockBean(UserService.class),
118
@MockBean(EmailService.class)
119
})
120
class MultipleMocksTest {
121
// Test implementation
122
}
123
```
124
125
### @SpyBean Annotation
126
127
Creates and injects Mockito spies into the Spring application context.
128
129
```java { .api }
130
/**
131
* Annotation that can be used to apply Mockito spies to a Spring ApplicationContext
132
* @since 1.4.0
133
* @deprecated since 3.4.0 for removal in Spring Boot 4.0.0. Use {@code @MockitoSpyBean} from Spring Framework instead.
134
*/
135
@SuppressWarnings("removal")
136
@Deprecated(since = "3.4.0", forRemoval = true)
137
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
138
@Retention(RetentionPolicy.RUNTIME)
139
@Documented
140
@Repeatable(SpyBeans.class)
141
public @interface SpyBean {
142
/**
143
* The name of the bean to spy upon
144
*/
145
String name() default "";
146
147
/**
148
* The classes to spy upon
149
*/
150
Class<?>[] classes() default {};
151
152
/**
153
* When to reset the spy
154
*/
155
MockReset reset() default MockReset.AFTER;
156
157
/**
158
* Whether the spy should be proxy target aware
159
*/
160
boolean proxyTargetAware() default true;
161
}
162
163
/**
164
* Container annotation for @SpyBean
165
* @deprecated since 3.4.0 for removal in Spring Boot 4.0.0. Use {@code @MockitoSpyBean} from Spring Framework instead.
166
*/
167
@SuppressWarnings("removal")
168
@Deprecated(since = "3.4.0", forRemoval = true)
169
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
170
@Retention(RetentionPolicy.RUNTIME)
171
@Documented
172
public @interface SpyBeans {
173
SpyBean[] value();
174
}
175
```
176
177
**Usage Examples:**
178
179
```java
180
@SpringBootTest
181
class SpyBeanTest {
182
183
@SpyBean
184
private UserService userService;
185
186
@Test
187
void spyOnRealService() {
188
// Real method will be called, but we can verify and stub
189
User realUser = userService.findByEmail("real@example.com");
190
191
// Verify the real method was called
192
verify(userService).findByEmail("real@example.com");
193
194
// Stub a method for specific behavior
195
doReturn(new User("stubbed@example.com", "Stubbed User"))
196
.when(userService).findByEmail("stubbed@example.com");
197
198
User stubbedUser = userService.findByEmail("stubbed@example.com");
199
assertThat(stubbedUser.getName()).isEqualTo("Stubbed User");
200
}
201
}
202
```
203
204
### Mock Reset Options
205
206
Enumeration for controlling when mocks are reset.
207
208
```java { .api }
209
/**
210
* Options for when to reset mocks
211
* @since 1.4.0
212
*/
213
public enum MockReset {
214
/**
215
* Reset the mock before each test method
216
*/
217
BEFORE,
218
219
/**
220
* Reset the mock after each test method
221
*/
222
AFTER,
223
224
/**
225
* Don't reset the mock
226
*/
227
NONE
228
}
229
```
230
231
### Mock Infrastructure
232
233
Core classes that handle mock creation and lifecycle management.
234
235
```java { .api }
236
/**
237
* BeanPostProcessor to handle @MockBean and @SpyBean annotations
238
*/
239
public class MockitoPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {
240
/**
241
* Process bean before instantiation to inject mocks
242
*/
243
@Override
244
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName);
245
}
246
247
/**
248
* TestExecutionListener that resets mocks according to MockReset configuration
249
*/
250
public class ResetMocksTestExecutionListener extends AbstractTestExecutionListener {
251
/**
252
* Reset mocks before test method if configured
253
*/
254
@Override
255
public void beforeTestMethod(TestContext testContext);
256
257
/**
258
* Reset mocks after test method if configured
259
*/
260
@Override
261
public void afterTestMethod(TestContext testContext);
262
}
263
264
/**
265
* TestExecutionListener that handles Mockito setup and cleanup
266
*/
267
public class MockitoTestExecutionListener extends AbstractTestExecutionListener {
268
/**
269
* Initialize Mockito for the test
270
*/
271
@Override
272
public void beforeTestMethod(TestContext testContext);
273
274
/**
275
* Clean up Mockito after the test
276
*/
277
@Override
278
public void afterTestMethod(TestContext testContext);
279
}
280
281
/**
282
* MockResolver implementation for Spring Boot
283
*/
284
public class SpringBootMockResolver implements MockResolver {
285
/**
286
* Resolve mock instance for the given field
287
*/
288
@Override
289
public Object resolve(Field field, Object instance);
290
}
291
```
292
293
### Advanced Mock Configuration
294
295
Advanced patterns for mock configuration and usage.
296
297
**Usage Examples:**
298
299
```java
300
@SpringBootTest
301
class AdvancedMockTest {
302
303
// Mock with specific reset behavior
304
@MockBean(reset = MockReset.BEFORE)
305
private UserRepository userRepository;
306
307
// Mock with extra interfaces
308
@MockBean(extraInterfaces = {Serializable.class, Cloneable.class})
309
private PaymentService paymentService;
310
311
// Mock with custom answer
312
@MockBean(answer = Answers.CALLS_REAL_METHODS)
313
private AbstractUserService abstractUserService;
314
315
@Test
316
void advancedMockConfiguration() {
317
// Configure mock with fluent API
318
when(userRepository.findByEmail(anyString()))
319
.thenReturn(Optional.of(new User("test@example.com", "Test")))
320
.thenReturn(Optional.empty());
321
322
// First call returns user
323
Optional<User> first = userRepository.findByEmail("test1@example.com");
324
assertThat(first).isPresent();
325
326
// Second call returns empty
327
Optional<User> second = userRepository.findByEmail("test2@example.com");
328
assertThat(second).isEmpty();
329
330
// Verify call count
331
verify(userRepository, times(2)).findByEmail(anyString());
332
}
333
334
@Test
335
void mockWithCaptor() {
336
ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class);
337
338
// Method under test
339
userService.saveUser(new User("save@example.com", "Save User"));
340
341
// Capture and verify the argument
342
verify(userRepository).save(userCaptor.capture());
343
User capturedUser = userCaptor.getValue();
344
345
assertThat(capturedUser.getEmail()).isEqualTo("save@example.com");
346
assertThat(capturedUser.getName()).isEqualTo("Save User");
347
}
348
}
349
350
// Configuration class example for complex mocking
351
@TestConfiguration
352
static class MockConfig {
353
354
@Bean
355
@Primary
356
public UserService mockUserService() {
357
UserService mock = Mockito.mock(UserService.class);
358
359
// Pre-configure common mock behavior
360
when(mock.findByEmail(startsWith("admin")))
361
.thenReturn(new User("admin@example.com", "Admin"));
362
363
when(mock.findByEmail(startsWith("test")))
364
.thenReturn(new User("test@example.com", "Test User"));
365
366
return mock;
367
}
368
}
369
```
370
371
### Integration with Test Slices
372
373
Mock integration works seamlessly with Spring Boot test slices.
374
375
**Usage Examples:**
376
377
```java
378
@WebMvcTest(UserController.class)
379
class WebMvcMockTest {
380
381
@MockBean
382
private UserService userService;
383
384
@Autowired
385
private MockMvc mockMvc;
386
387
@Test
388
void controllerWithMockedService() throws Exception {
389
when(userService.findByEmail("test@example.com"))
390
.thenReturn(new User("test@example.com", "Test User"));
391
392
mockMvc.perform(get("/users/test@example.com"))
393
.andExpect(status().isOk())
394
.andExpect(jsonPath("$.email").value("test@example.com"))
395
.andExpect(jsonPath("$.name").value("Test User"));
396
397
verify(userService).findByEmail("test@example.com");
398
}
399
}
400
401
@DataJpaTest
402
class JpaRepositoryMockTest {
403
404
@TestEntityManager
405
private TestEntityManager entityManager;
406
407
@Autowired
408
private UserRepository userRepository;
409
410
@MockBean
411
private EmailService emailService; // Mock external service
412
413
@Test
414
void repositoryWithMockedExternalService() {
415
// Save entity using real repository
416
User user = new User("test@example.com", "Test User");
417
entityManager.persistAndFlush(user);
418
419
// Mock external service
420
when(emailService.sendWelcomeEmail(anyString())).thenReturn(true);
421
422
// Test service method that uses both repository and external service
423
boolean result = userService.registerUser("test@example.com", "Test User");
424
425
assertThat(result).isTrue();
426
verify(emailService).sendWelcomeEmail("test@example.com");
427
}
428
}
429
```