You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 2.5中如何Mock Service Bean内部依赖的另一Service方法

核心问题原因

@PostConstruct是Spring Bean初始化阶段的回调方法,执行时机远早于测试方法的运行时机。你之前的配置不生效,本质是Mock方法的打桩时机晚于A的@PostConstruct执行时机,等到你在测试方法中给B的方法打桩时,A的初始化逻辑已经跑完,调用的是B的原始方法。


可用解决方案

方案1:保留Spring上下文测试,提前定义Mock行为

如果你需要依赖Spring容器的完整能力,可以通过@TestConfiguration提前初始化打桩完成的Mock Bean,替换容器中的原始B实例,确保A初始化时拿到的就是已经打桩好的B:

@SpringBootTest
class TestClass {
    @Autowired
    private A a;
    // 注入容器中的Mock B实例,用于后续验证
    @Autowired
    private B b;
    
    @TestConfiguration
    static class MockBConfig {
        @Bean
        @Primary
        public B mockedB() {
            B mockB = Mockito.mock(B.class);
            // 提前对目标方法打桩
            Mockito.doNothing().when(mockB).methodToBeMocked();
            // 若方法有返回值,写法为 Mockito.when(mockB.xxx()).thenReturn(自定义返回值);
            return mockB;
        }
    }

    @Test
    void mytest() {
        a.anyMethod();
        // 可验证@PostConstruct中的方法调用符合预期
        Mockito.verify(b, Mockito.times(1)).methodToBeMocked();
    }
}

方案2:纯Mockito单元测试(无Spring上下文,性能更高)

如果不需要Spring容器的其他能力,直接用Mockito完成依赖注入和初始化,完全可控执行顺序:

@ExtendWith(MockitoExtension.class)
class TestClass {
    // 自动实例化A,将下方的Mock B注入到A中
    @InjectMocks
    private A a;
    
    @Mock
    private B b;

    @BeforeEach
    void init() {
        // 先对B的方法打桩
        Mockito.doNothing().when(b).methodToBeMocked();
        // 手动触发A的@PostConstruct逻辑
        a.postconstruct();
    }

    @Test
    void mytest() {
        a.anyMethod();
        Mockito.verify(b, Mockito.times(1)).methodToBeMocked();
    }
}

注意事项
  • 不要把Mock方法的打桩逻辑写在@Test测试方法内部,此时A的@PostConstruct已经执行完成,打桩不会生效
  • 注意方法名、参数的拼写完全匹配,否则Mockito会匹配不到目标方法,打桩失效
  • 如果使用@MockBean注解,打桩逻辑需要写在@BeforeEach方法中,才能赶在Spring上下文初始化前生效

内容的提问来源于stack exchange,提问作者icordoba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 17:06:03