CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework--spring-test

Spring TestContext Framework for comprehensive integration testing of Spring applications

Overview
Eval results
Files

bean-override-framework.mddocs/

Bean Override Framework

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.

Capabilities

MockitoBean Annotation

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
    }
}

MockitoSpyBean Annotation

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);
    }
}

TestBean Annotation

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();
    }
}

MockReset Enum

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

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();
}

BeanOverrideTestExecutionListener

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;
}

Types

/**
 * 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

docs

bean-override-framework.md

index.md

jdbc-testing.md

junit-integration.md

mock-objects.md

testcontext-framework.md

testing-annotations.md

web-testing.md

tile.json