Spring TestContext Framework for comprehensive integration testing of Spring applications
The Bean Override Framework (since Spring Framework 6.2) provides a modern, unified approach for overriding beans in Spring tests. It offers better performance and integration compared to older mechanisms, with support for Mockito mocks/spies and custom factory methods.
Creates Mockito mocks to override beans in the ApplicationContext. Can be applied to fields or at the type level for comprehensive bean overriding.
/**
* Annotation that can be used to add mocks to a Spring ApplicationContext.
* Can be used as a field annotation or on the class level.
*/
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(MockitoBeans.class)
@BeanOverride(MockitoBeanOverrideProcessor.class)
public @interface MockitoBean {
/**
* The name of the bean to register or replace. If not specified, the field name is used.
* @return the name of the bean
*/
@AliasFor("name")
String value() default "";
/**
* The name of the bean to register or replace. If not specified, the field name is used.
* @return the name of the bean
*/
@AliasFor("value")
String name() default "";
/**
* The classes that the mock should extend. If not specified, the field type is used.
* @return the classes for the mock to extend
*/
Class<?>[] types() default {};
/**
* The name of the application context where the mock should be added.
* @return the context name
*/
String contextName() default "";
/**
* Any extra interfaces that should be supported by the mock.
* @return the extra interfaces
*/
Class<?>[] extraInterfaces() default {};
/**
* The answers mode to use on the created mock.
* @return the answers mode
*/
Answers answers() default Answers.RETURNS_DEFAULTS;
/**
* If the generated mock is serializable.
* @return true if the mock is serializable
*/
boolean serializable() default false;
/**
* The reset mode to apply to the mock bean. The default is MockReset.AFTER meaning
* that mocks are automatically reset after each test method is invoked.
* @return the reset mode
*/
MockReset reset() default MockReset.AFTER;
/**
* Indicates that the annotated field requires that a bean being overridden exists.
* @return true if a bean override is required
*/
boolean enforceOverride() default false;
}Usage Examples:
@SpringBootTest
class UserServiceTest {
@MockitoBean
private UserRepository userRepository;
@MockitoBean(name = "specialService")
private SpecialService specialService;
@Test
void testUserCreation() {
when(userRepository.save(any(User.class)))
.thenReturn(new User("John", "john@example.com"));
// Test logic using mocked userRepository
}
}Creates Mockito spies to wrap existing beans in the ApplicationContext, allowing partial mocking where some methods use real implementations.
/**
* Annotation that can be used to apply Mockito spies to a Spring ApplicationContext.
* Can be used as a field annotation or on the class level.
*/
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(MockitoSpyBeans.class)
@BeanOverride(MockitoBeanOverrideProcessor.class)
public @interface MockitoSpyBean {
/**
* The name of the bean to spy upon. If not specified, the field name is used.
* @return the name of the bean
*/
@AliasFor("name")
String value() default "";
/**
* The name of the bean to spy upon. If not specified, the field name is used.
* @return the name of the bean
*/
@AliasFor("value")
String name() default "";
/**
* The classes that the spy should be based on. If not specified, the field type is used.
* @return the classes for the spy
*/
Class<?>[] types() default {};
/**
* The name of the application context where the spy should be applied.
* @return the context name
*/
String contextName() default "";
/**
* The reset mode to apply to the spy bean.
* @return the reset mode
*/
MockReset reset() default MockReset.AFTER;
}Usage Examples:
@SpringBootTest
class EmailServiceTest {
@MockitoSpyBean
private EmailService emailService;
@Test
void testEmailSending() {
// Spy on real EmailService, but mock specific methods
doNothing().when(emailService).sendEmail(anyString(), anyString());
// Other methods use real implementation
boolean isValid = emailService.validateEmail("test@example.com");
assertTrue(isValid);
}
}Overrides beans using static factory methods, following convention-based discovery or explicit method naming for creating test-specific bean implementations.
/**
* Annotation that can be used to override beans in a Spring ApplicationContext
* using a static factory method.
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@BeanOverride(TestBeanOverrideProcessor.class)
@Reflective(TestBeanReflectiveProcessor.class)
public @interface TestBean {
/**
* The name of the bean to override. If not specified, the field name is used.
* @return the name of the bean
*/
@AliasFor("name")
String value() default "";
/**
* The name of the bean to override. If not specified, the field name is used.
* @return the name of the bean
*/
@AliasFor("value")
String name() default "";
/**
* The name of the static method to use for creating the bean override.
* If not specified, convention-based method discovery is used.
* @return the method name
*/
String methodName() default "";
/**
* The name of the application context where the bean should be overridden.
* @return the context name
*/
String contextName() default "";
/**
* Indicates that the annotated field requires that a bean being overridden exists.
* @return true if a bean override is required
*/
boolean enforceOverride() default false;
}Usage Examples:
@SpringBootTest
class PaymentServiceTest {
@TestBean
private PaymentProcessor paymentProcessor;
@TestBean(methodName = "createCustomNotificationService")
private NotificationService notificationService;
@Test
void testPaymentProcessing() {
// Test using overridden beans from factory methods
}
// Convention-based factory method (matches field name)
static PaymentProcessor paymentProcessor() {
return new MockPaymentProcessor();
}
// Explicit factory method
static NotificationService createCustomNotificationService() {
return new TestNotificationService();
}
}Controls when Mockito mocks and spies are reset during test execution.
/**
* Reset mode to apply to a mock bean. Usually applied to a mock that is shared across several test methods.
*/
public enum MockReset {
/**
* Reset the mock before the test method runs. This option ensures the mock is reset
* before each test method, which is useful when you need a clean mock state.
*/
BEFORE,
/**
* Reset the mock after the test method runs. This is the default option and
* ensures that mock interactions don't leak between test methods.
*/
AFTER,
/**
* Do not reset the mock. Use this option when you want to preserve mock state
* across multiple test methods or when manually managing mock resets.
*/
NONE;
/**
* Create MockSettings with BEFORE reset mode.
* @return MockSettings configured for reset before test methods
*/
public static MockSettings before();
/**
* Create MockSettings with AFTER reset mode.
* @return MockSettings configured for reset after test methods
*/
public static MockSettings after();
/**
* Create MockSettings with the specified reset mode.
* @param reset the reset mode to apply
* @return MockSettings with the specified reset configuration
*/
public static MockSettings withSettings(MockReset reset);
/**
* Apply the reset mode to existing MockSettings.
* @param reset the reset mode to apply
* @param settings existing MockSettings to modify
* @return modified MockSettings with reset configuration
*/
public static MockSettings apply(MockReset reset, MockSettings settings);
}Container annotations for repeatable @MockitoBean and @MockitoSpyBean usage.
/**
* Container annotation that aggregates several @MockitoBean annotations.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MockitoBeans {
/**
* @return the contained @MockitoBean annotations
*/
MockitoBean[] value();
}
/**
* Container annotation that aggregates several @MockitoSpyBean annotations.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MockitoSpyBeans {
/**
* @return the contained @MockitoSpyBean annotations
*/
MockitoSpyBean[] value();
}TestExecutionListener that enables Bean Override support by processing annotations and injecting overridden beans.
/**
* TestExecutionListener which provides support for Bean Override annotations.
*/
public class BeanOverrideTestExecutionListener extends AbstractTestExecutionListener {
/**
* The order of this listener - runs early to set up bean overrides.
*/
public static final int ORDER = 1950;
/**
* Get the order of this listener.
* @return the order value
*/
@Override
public int getOrder();
/**
* Prepare the test instance by injecting bean override fields.
* @param testContext the test context
* @throws Exception if preparation fails
*/
@Override
public void prepareTestInstance(TestContext testContext) throws Exception;
/**
* Prepare for test method execution by resetting mocks if configured.
* @param testContext the test context
* @throws Exception if preparation fails
*/
@Override
public void beforeTestMethod(TestContext testContext) throws Exception;
}/**
* Strategy for how a bean override should be processed.
*/
public enum BeanOverrideStrategy {
/**
* Replace a given bean, immediately preparing a singleton instance.
* Fails if the original bean does not exist.
*/
REPLACE,
/**
* Replace or create a given bean, immediately preparing a singleton instance.
* Creates a new bean if the target bean does not exist.
*/
REPLACE_OR_CREATE,
/**
* Intercept and process an early bean reference, allowing variants of bean
* overriding to wrap the original bean instance.
*/
WRAP
}
/**
* Meta-annotation for creating custom bean override annotations.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
@Documented
@Reflective(BeanOverrideReflectiveProcessor.class)
public @interface BeanOverride {
/**
* The BeanOverrideProcessor implementation to use.
* @return the processor class
*/
Class<? extends BeanOverrideProcessor> value();
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework--spring-test