SpringBootTest中如何在Autowired前完成Bean的Mock配置?
问题原因
你遇到的核心问题是Spring容器初始化Bean的时机早于Mock行为的设置时机:
- 使用
@MockBean时,Spring会先创建Mock实例并加入容器,随后初始化ClassC和ClassA(调用它们的构造方法),而你的@BeforeAll方法是在所有Bean初始化完成后才执行的,此时构造方法已经调用过b.get(),自然返回Mock的默认值null。 - 用
MockitoExtension+@InjectMocks时,Mockito会先初始化@Mock,再自动实例化@InjectMocks标注的Bean(调用构造方法),最后才执行@BeforeAll,同样导致构造时Mock未配置行为。
解决思路
方案1:基于Spring容器,提前配置Mock行为
直接通过@Bean方法创建并配置好Mock的ClassB,让Spring容器在初始化ClassC和ClassA之前就拿到已经设置好返回值的Mock实例:
@ExtendWith(SpringExtension.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) @EnableConfigurationProperties @SpringBootTest(classes = {ClassA.class, ClassC.class}) public class SomeTest { @Bean public ClassB b() { ClassB mockB = Mockito.mock(ClassB.class); Mockito.when(mockB.get()).thenReturn("koo"); return mockB; } @Autowired private ClassC c; @Autowired private ClassA a; @Test void test() { // 执行测试逻辑 } }
方案2:纯Mockito单元测试,手动控制实例化顺序
如果不需要启动Spring容器,完全用Mockito做单元测试,需要先配置Mock的行为,再手动实例化ClassC和ClassA,确保构造方法调用时Mock已经准备好:
@ExtendWith(MockitoExtension.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class SomeTest { @Mock private ClassB b; private ClassC c; private ClassA a; @BeforeAll void setup() { // 先配置Mock行为 Mockito.when(b.get()).thenReturn("koo"); // 再手动实例化依赖Mock的Bean c = new ClassC(b); a = new ClassA(b, c); } @Test void test() { // 执行测试逻辑 } }
这两种方案都能保证ClassC和ClassA构造时,b.get()返回的是你预期的"koo",从而得到想要的打印结果。
内容的提问来源于stack exchange,提问作者Lamming
相关产品推荐
相关产品推荐

