Spring Boot Junit测试中如何正确配置@Configuration类以mock依赖的@ConfigurationProperties
问题根因
你遇到的mock返回null问题核心有两个:
- 你@Autowired注入的@Configuration类是Spring生成的CGLIB代理对象,依赖注入受Spring上下文管控,你手动mock的ConfigurationProperties没有被正确注入到代理对应的原始实例中
- 默认Spring上下文初始化时会优先加载真实的ConfigurationProperties bean,不会自动使用你生成的mock对象
推荐解决方案
方案1:纯单元测试(无需启动Spring上下文,性能最优)
直接实例化配置类,手动注入mock的Properties对象,完全脱离Spring代理逻辑的影响,适合只测业务逻辑的场景:
@ExtendWith(MockitoExtension.class) public class MyConfigurationTest { // Mock所有依赖的ConfigurationProperties类 @Mock private CustomProperties1 customProperties1; @Mock private CustomProperties2 customProperties2; // 直接把配置类作为被测对象,mock会自动注入 @InjectMocks private MyConfig myConfig; @Test void testProtectedLogic() throws Exception { // 给mock对象打桩 when(customProperties1.getTimeout()).thenReturn(1000); when(customProperties2.getEnableCache()).thenReturn(true); // 调用protected方法,如果测试类和配置类同包,可直接调用无需反射 Method targetMethod = MyConfig.class.getDeclaredMethod("yourProtectedMethod"); targetMethod.setAccessible(true); Object result = targetMethod.invoke(myConfig); // 验证返回结果符合预期 assertThat(result).isNotNull(); } }
你可以把配置类里的protected方法改成包级访问权限,同包的测试类可以直接调用,不需要写反射代码。
方案2:Spring上下文集成测试(需验证@Bean注册逻辑时使用)
如果需要验证Bean在Spring上下文的注册逻辑,需要用@MockBean替换上下文里的真实Properties bean,Spring会自动把mock对象注入到配置类中:
@SpringBootTest(classes = MyConfig.class) @EnableConfigurationProperties(value = {CustomProperties1.class, CustomProperties2.class}) public class MyConfigSpringTest { // 替换上下文中的真实Properties为mock对象 @MockBean private CustomProperties1 customProperties1; @MockBean private CustomProperties2 customProperties2; @Autowired private MyConfig myConfig; @Autowired private ApplicationContext context; @Test void testBeanRegistration() { // 给mock对象打桩 when(customProperties1.getServiceUrl()).thenReturn("https://test.api.com"); // 从上下文获取@Bean方法生成的实例验证 CustomService customService = context.getBean(CustomService.class); assertThat(customService.getApiUrl()).isEqualTo("https://test.api.com"); } }
注意事项
- 不要在测试中直接调用配置类的@Bean方法,配置类的代理会拦截@Bean方法调用,多次调用默认返回同一个单例实例,直接调用你提取的业务逻辑方法即可
- 除非必须验证Spring上下文的Bean加载逻辑,否则优先选择方案1的纯单元测试,执行速度更快,mock逻辑更可控
内容的提问来源于stack exchange,提问作者Moritz Kolbe
相关产品推荐
相关产品推荐

