Starter for testing Spring Boot applications with libraries including JUnit Jupiter, Hamcrest and Mockito
—
Seamless Mockito integration with Spring context for mocking beans and services in Spring Boot tests.
⚠️ Deprecation Notice: As of Spring Boot 3.4.0,
@MockBeanand@SpyBeanare deprecated for removal. Use@MockitoBeanand@MockitoSpyBeanfrom Spring Framework 6.2+ instead:
org.springframework.test.context.bean.override.mockito.MockitoBeanorg.springframework.test.context.bean.override.mockito.MockitoSpyBean
Creates and injects Mockito mocks into the Spring application context.
/**
* Annotation that can be used to add mocks to a Spring ApplicationContext
* @since 1.4.0
* @deprecated since 3.4.0 for removal in Spring Boot 4.0.0. Use {@code @MockitoBean} from Spring Framework instead.
*/
@SuppressWarnings("removal")
@Deprecated(since = "3.4.0", forRemoval = true)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(MockBeans.class)
public @interface MockBean {
/**
* The name of the bean to register or replace
*/
String name() default "";
/**
* The classes to mock
*/
Class<?>[] classes() default {};
/**
* Extra interfaces that should also be declared on the mock
*/
Class<?>[] extraInterfaces() default {};
/**
* The Mockito Answer to use on the mock
*/
Answers answer() default Answers.RETURNS_DEFAULTS;
/**
* Whether the mock is serializable
*/
boolean serializable() default false;
/**
* When to reset the mock
*/
MockReset reset() default MockReset.AFTER;
}
/**
* Container annotation for @MockBean
* @deprecated since 3.4.0 for removal in Spring Boot 4.0.0. Use {@code @MockitoBean} from Spring Framework instead.
*/
@SuppressWarnings("removal")
@Deprecated(since = "3.4.0", forRemoval = true)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MockBeans {
MockBean[] value();
}Usage Examples:
@SpringBootTest
class MockBeanTest {
@MockBean
private UserService userService;
@MockBean
private EmailService emailService;
@Autowired
private UserController userController;
@Test
void mockBeanIsInjected() {
// Mock behavior
User mockUser = new User("test@example.com", "Test User");
when(userService.findByEmail("test@example.com")).thenReturn(mockUser);
// Test controller using mocked service
ResponseEntity<User> response = userController.getUser("test@example.com");
assertThat(response.getBody()).isEqualTo(mockUser);
verify(userService).findByEmail("test@example.com");
}
@Test
void mockWithCustomAnswer() {
// Configure mock with custom answer
when(userService.findByEmail(anyString()))
.thenAnswer(invocation -> {
String email = invocation.getArgument(0);
return new User(email, "Generated User");
});
User user = userService.findByEmail("any@example.com");
assertThat(user.getEmail()).isEqualTo("any@example.com");
assertThat(user.getName()).isEqualTo("Generated User");
}
}
// Multiple mocks with container annotation
@MockBeans({
@MockBean(UserService.class),
@MockBean(EmailService.class)
})
class MultipleMocksTest {
// Test implementation
}Creates and injects Mockito spies into the Spring application context.
/**
* Annotation that can be used to apply Mockito spies to a Spring ApplicationContext
* @since 1.4.0
* @deprecated since 3.4.0 for removal in Spring Boot 4.0.0. Use {@code @MockitoSpyBean} from Spring Framework instead.
*/
@SuppressWarnings("removal")
@Deprecated(since = "3.4.0", forRemoval = true)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(SpyBeans.class)
public @interface SpyBean {
/**
* The name of the bean to spy upon
*/
String name() default "";
/**
* The classes to spy upon
*/
Class<?>[] classes() default {};
/**
* When to reset the spy
*/
MockReset reset() default MockReset.AFTER;
/**
* Whether the spy should be proxy target aware
*/
boolean proxyTargetAware() default true;
}
/**
* Container annotation for @SpyBean
* @deprecated since 3.4.0 for removal in Spring Boot 4.0.0. Use {@code @MockitoSpyBean} from Spring Framework instead.
*/
@SuppressWarnings("removal")
@Deprecated(since = "3.4.0", forRemoval = true)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SpyBeans {
SpyBean[] value();
}Usage Examples:
@SpringBootTest
class SpyBeanTest {
@SpyBean
private UserService userService;
@Test
void spyOnRealService() {
// Real method will be called, but we can verify and stub
User realUser = userService.findByEmail("real@example.com");
// Verify the real method was called
verify(userService).findByEmail("real@example.com");
// Stub a method for specific behavior
doReturn(new User("stubbed@example.com", "Stubbed User"))
.when(userService).findByEmail("stubbed@example.com");
User stubbedUser = userService.findByEmail("stubbed@example.com");
assertThat(stubbedUser.getName()).isEqualTo("Stubbed User");
}
}Enumeration for controlling when mocks are reset.
/**
* Options for when to reset mocks
* @since 1.4.0
*/
public enum MockReset {
/**
* Reset the mock before each test method
*/
BEFORE,
/**
* Reset the mock after each test method
*/
AFTER,
/**
* Don't reset the mock
*/
NONE
}Core classes that handle mock creation and lifecycle management.
/**
* BeanPostProcessor to handle @MockBean and @SpyBean annotations
*/
public class MockitoPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {
/**
* Process bean before instantiation to inject mocks
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName);
}
/**
* TestExecutionListener that resets mocks according to MockReset configuration
*/
public class ResetMocksTestExecutionListener extends AbstractTestExecutionListener {
/**
* Reset mocks before test method if configured
*/
@Override
public void beforeTestMethod(TestContext testContext);
/**
* Reset mocks after test method if configured
*/
@Override
public void afterTestMethod(TestContext testContext);
}
/**
* TestExecutionListener that handles Mockito setup and cleanup
*/
public class MockitoTestExecutionListener extends AbstractTestExecutionListener {
/**
* Initialize Mockito for the test
*/
@Override
public void beforeTestMethod(TestContext testContext);
/**
* Clean up Mockito after the test
*/
@Override
public void afterTestMethod(TestContext testContext);
}
/**
* MockResolver implementation for Spring Boot
*/
public class SpringBootMockResolver implements MockResolver {
/**
* Resolve mock instance for the given field
*/
@Override
public Object resolve(Field field, Object instance);
}Advanced patterns for mock configuration and usage.
Usage Examples:
@SpringBootTest
class AdvancedMockTest {
// Mock with specific reset behavior
@MockBean(reset = MockReset.BEFORE)
private UserRepository userRepository;
// Mock with extra interfaces
@MockBean(extraInterfaces = {Serializable.class, Cloneable.class})
private PaymentService paymentService;
// Mock with custom answer
@MockBean(answer = Answers.CALLS_REAL_METHODS)
private AbstractUserService abstractUserService;
@Test
void advancedMockConfiguration() {
// Configure mock with fluent API
when(userRepository.findByEmail(anyString()))
.thenReturn(Optional.of(new User("test@example.com", "Test")))
.thenReturn(Optional.empty());
// First call returns user
Optional<User> first = userRepository.findByEmail("test1@example.com");
assertThat(first).isPresent();
// Second call returns empty
Optional<User> second = userRepository.findByEmail("test2@example.com");
assertThat(second).isEmpty();
// Verify call count
verify(userRepository, times(2)).findByEmail(anyString());
}
@Test
void mockWithCaptor() {
ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class);
// Method under test
userService.saveUser(new User("save@example.com", "Save User"));
// Capture and verify the argument
verify(userRepository).save(userCaptor.capture());
User capturedUser = userCaptor.getValue();
assertThat(capturedUser.getEmail()).isEqualTo("save@example.com");
assertThat(capturedUser.getName()).isEqualTo("Save User");
}
}
// Configuration class example for complex mocking
@TestConfiguration
static class MockConfig {
@Bean
@Primary
public UserService mockUserService() {
UserService mock = Mockito.mock(UserService.class);
// Pre-configure common mock behavior
when(mock.findByEmail(startsWith("admin")))
.thenReturn(new User("admin@example.com", "Admin"));
when(mock.findByEmail(startsWith("test")))
.thenReturn(new User("test@example.com", "Test User"));
return mock;
}
}Mock integration works seamlessly with Spring Boot test slices.
Usage Examples:
@WebMvcTest(UserController.class)
class WebMvcMockTest {
@MockBean
private UserService userService;
@Autowired
private MockMvc mockMvc;
@Test
void controllerWithMockedService() throws Exception {
when(userService.findByEmail("test@example.com"))
.thenReturn(new User("test@example.com", "Test User"));
mockMvc.perform(get("/users/test@example.com"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.email").value("test@example.com"))
.andExpect(jsonPath("$.name").value("Test User"));
verify(userService).findByEmail("test@example.com");
}
}
@DataJpaTest
class JpaRepositoryMockTest {
@TestEntityManager
private TestEntityManager entityManager;
@Autowired
private UserRepository userRepository;
@MockBean
private EmailService emailService; // Mock external service
@Test
void repositoryWithMockedExternalService() {
// Save entity using real repository
User user = new User("test@example.com", "Test User");
entityManager.persistAndFlush(user);
// Mock external service
when(emailService.sendWelcomeEmail(anyString())).thenReturn(true);
// Test service method that uses both repository and external service
boolean result = userService.registerUser("test@example.com", "Test User");
assertThat(result).isTrue();
verify(emailService).sendWelcomeEmail("test@example.com");
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter-test