Spring Modulith集成测试中Feign客户端的@ApplicationModuleTest问题
解决Spring Modulith @ApplicationModuleTest与Spring Cloud OpenFeign模块隔离冲突问题
问题场景
- 基于Spring Boot 3.1 + Spring Modulith 1.2.4构建多模块项目,包含
amadeus和collinson两个独立模块 - 每个模块分别实现了
AmadeusFeignClient和CollinsonFeignClient - 生产环境运行正常,但使用
@ApplicationModuleTest做单模块集成测试时出现异常:- 测试
AmadeusService时,提示找不到CollinsonFeignClientBean - 测试
CollinsonService时,提示找不到AmadeusFeignClientBean
- 测试
- 改用
@SpringBootTest则测试正常,核心原因是Spring Cloud OpenFeign未遵循@ApplicationModuleTest的模块隔离规则
原因分析
@ApplicationModuleTest会严格依据Spring Modulith的模块边界加载Bean,仅加载当前测试模块及其声明依赖的模块组件。但Spring Cloud OpenFeign的默认自动配置会全局扫描所有标注@FeignClient的类,不管这些类所属模块是否被当前测试上下文纳入加载范围,导致测试时尝试加载未被隔离规则允许的FeignClient,最终触发Bean找不到的异常。
解决方案
方案1:为每个模块限定Feign扫描范围
在每个模块的配置类中,通过@EnableFeignClients指定仅扫描当前模块的FeignClient,避免全局扫描:
// amadeus模块的Feign配置类 @Configuration @EnableFeignClients(basePackages = "com.yourproject.amadeus.feign") public class AmadeusFeignConfig { }
// collinson模块的Feign配置类 @Configuration @EnableFeignClients(basePackages = "com.yourproject.collinson.feign") public class CollinsonFeignConfig { }
这样@ApplicationModuleTest加载当前模块时,只会初始化本模块内的FeignClient,不会尝试加载其他模块的组件。
方案2:测试中排除Feign全局自动配置
使用@ApplicationModuleTest的excludeAutoConfiguration属性关闭Feign的全局自动配置,手动引入当前模块的Feign配置:
@ApplicationModuleTest( module = AmadeusModule.class, excludeAutoConfiguration = FeignAutoConfiguration.class ) @Import(AmadeusFeignConfig.class) class AmadeusServiceTest { // 测试逻辑 }
该方式直接切断Feign的全局扫描逻辑,仅加载当前模块所需的Feign配置和客户端。
方案3:为跨模块依赖的FeignClient提供Mock替身
如果当前模块的业务逻辑依赖了其他模块的FeignClient,可在测试中用@MockBean替代真实的FeignClient,隔离外部依赖:
@ApplicationModuleTest(module = AmadeusModule.class) class AmadeusServiceTest { @MockBean private CollinsonFeignClient collinsonFeignClient; @Test void testAmadeusServiceLogic() { // 定义collinsonFeignClient的Mock行为 when(collinsonFeignClient.someMethod(any())).thenReturn(mockResult); // 执行测试逻辑 } }
此方案适合模块间存在业务依赖的场景,专注测试当前模块的核心逻辑,无需加载其他模块的真实组件。
内容的提问来源于stack exchange,提问作者Mr. Kadiev
相关产品推荐
相关产品推荐

