Spring Cloud Gateway单元测试中GlobalFilter依赖注入失效
你遇到的这个问题核心原因是测试环境的Spring上下文没有启用注解驱动支持,或者没有为AuthenticationGlobalFilter手动注入Permission依赖,导致@Autowired注解在测试时未被Spring处理,而生产环境的配置里已经开启了相关支持,所以运行正常。
具体原因拆解
生产环境的api-gateway-unico-beans.xml中配置了<context:annotation-config />,这个配置会激活Spring的注解处理器,让@Autowired这类注解生效;同时你也在xml里定义了permission和AuthenticationGlobalFilter的bean,Spring会自动完成依赖注入。
但测试环境的authentication-filter-test-beans.xml里:
- 没有配置
<context:annotation-config />或<context:component-scan>,Spring不会识别@Autowired注解 - 定义
authenticationFilterbean时,没有手动指定permission的依赖注入
接下来给你几个可行的解决方案:
方案一:在测试配置中启用注解驱动
修改authentication-filter-test-beans.xml,添加注解驱动配置,让Spring处理@Autowired:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <import resource="classpath:api-gateway-unico-test-beans.xml" /> <!-- 启用注解驱动,让@Autowired生效 --> <context:annotation-config /> <bean id="authenticationFilter" class="*****.apigatewayunico.filters.AuthenticationGlobalFilter" /> </beans>
同时确保api-gateway-unico-test-beans.xml中已经正确定义了permission的bean(比如你测试用的mock实例)。
方案二:手动为测试bean注入依赖
如果不想启用注解驱动,可以直接在测试xml里手动注入Permission到AuthenticationGlobalFilter:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <import resource="classpath:api-gateway-unico-test-beans.xml" /> <bean id="authenticationFilter" class="*****.apigatewayunico.filters.AuthenticationGlobalFilter"> <!-- 手动注入permission依赖 --> <property name="permission" ref="permission" /> </bean> </beans>
这种方式不需要依赖注解,直接通过XML配置完成依赖注入,适合不想修改注解配置的场景。
方案三:改用Spring组件扫描简化配置
更优雅的方式是把AuthenticationGlobalFilter标记为Spring组件,去掉XML里的手动bean定义:
- 在
AuthenticationGlobalFilter类上添加@Component注解:
@Component // 添加这个注解 public class AuthenticationGlobalFilter implements GlobalFilter, Ordered { @Autowired private Permission permission; // ... 其他代码 }
- 修改测试配置,要么在
TestConfig类上添加@ComponentScan指定过滤器所在包,要么在测试XML里添加<context:component-scan base-package="*****.apigatewayunico.filters" />,同时移除XML里的authenticationFilterbean定义。 - 测试中可以用
@MockBean来自动创建Permission的mock实例,替代XML配置:
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT) @DirtiesContext public class AuthenticationGlobalFilterIntegrationTests extends BaseWebClientTests { @MockBean // 用这个注解自动创建mock的Permission private Permission permission; @Before public void setup() { super.setup(); reset(permission); } // ... 测试方法 }
这种方式完全摆脱XML配置,更符合Spring Boot的最佳实践,测试代码也更简洁。
内容的提问来源于stack exchange,提问作者Sam

