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.