Skip to content

Replacing Deprecated @MockBeans in Spring Boot 3.4+ ​

Problem Statement ​

Since Spring Boot 3.4.0, the @MockBean and @MockBeans annotations have been deprecated in favor of the new @MockitoBean annotation. This change affects developers who use these annotations to create custom meta-annotations for group mocking multiple dependencies in tests.

The challenge arises when migrating existing compositions like:

java
@MockBeans({
    @MockBean(ServiceA.class),
    @MockBean(ServiceB.class),
    @MockBean(ServiceC.class)
})

Without a direct @MockitoBeans replacement, developers with numerous mocks (20+) face tedious manual declarations in each test class.

Solution ​

With Spring Boot 3.4+, replace class-level @MockBeans with @MockitoBean using its types attribute to specify multiple beans. This approach maintains the grouped mocking behavior while using the new annotation system.

Migration Steps ​

  1. Replace @MockBeans with @MockitoBean
  2. Convert individual @MockBean entries to the types array
  3. Update package imports

Here's how to rewrite the custom annotation:

java
import org.springframework.test.context.bean.override.mockito.MockitoBean;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
// Old approach: @MockBeans({@MockBean(ServiceA.class), ...})
@MockitoBean(types = {ServiceA.class, ServiceB.class, ServiceC.class})
public @interface MyMocksTest {
}

Field-Level Migration ​

For individual field mocks:

java
// Old: @MockBean
@MockitoBean
private ServiceA serviceA;

// Spy beans replacement
@MockitoSpyBean // Replaces @SpyBean
private ServiceB serviceB;

Key Differences Explained ​

  • Class-Level Support: @MockitoBean(types = {...}) replaces the deprecated @MockBeans container
  • Repeatable Annotation: @MockitoBean can be repeated at type level instead of using a container:
    java
    @MockitoBean(ServiceA.class)
    @MockitoBean(ServiceB.class)
    public @interface MyMocksTest {}
  • New Location: Import from org.springframework.test.context.bean.override.mockito
  • Same Behavior: Null returns for unstubbed methods and automatic application context integration remain unchanged

Compatibility Note

While deprecated annotations remain functional until Spring Boot 3.5, migrating avoids technical debt

Additional Recommendations ​

  1. Group Common Mocks: Organize mock definitions by module or functionality
    java
    @MockitoBean(types = {PaymentService.class, InvoiceService.class})
    public @interface FinancialMocks {}
  2. Custom Qualifiers: For beans needing qualification, use name attribute:
    java
    @MockitoBean(value = "mainDataSource", types = DataSource.class)
  3. Annotation Composition: Combine with other test annotations:
    java
    @SpringBootTest
    @MyMocksTest
    @ActiveProfiles("test")
    public class MyIntegrationTest { ... }

Conclusion ​

Migrating from deprecated @MockBeans to @MockitoBean is straightforward using the types attribute for class-level definitions. This approach maintains test conciseness while adopting Spring Boot 3.4+'s improved mocking strategy. Implement these changes before the deprecated annotations are removed in future versions.