Spring Webflux集成测试:WebTestClient注入与Redis启动顺序问题
我之前也碰到过类似的坑,给你两个方向的解决方案,应该能搞定你的问题:
方案一:无需启动Web环境即可注入WebTestClient
默认情况下,@SpringBootTest的webEnvironment是MOCK模式,这时候Spring不会自动创建WebTestClient的Bean。你只需要加上@AutoConfigureWebTestClient注解,就能触发WebTestClient的自动配置:
@SpringBootTest @ActiveProfiles("test") @AutoConfigureWebTestClient // 关键注解,自动配置WebTestClient class FooControllerIT { @Autowired private WebTestClient webTestClient; // 测试方法示例 @Test void testFooEndpoint() { webTestClient.get().uri("/foo") .exchange() .expectStatus().isOk(); } }
如果不想用自动配置,也可以手动绑定到应用上下文构建WebTestClient:
@SpringBootTest @ActiveProfiles("test") class FooControllerIT { private WebTestClient webTestClient; @Autowired public void setUp(ApplicationContext context) { // 手动绑定上下文,创建WebTestClient webTestClient = WebTestClient.bindToApplicationContext(context).build(); } // 测试方法... }
方案二:让嵌入式Redis配置优先于Redisson加载
如果还是需要启动Web环境,或者想彻底解决Redisson连接问题,核心是确保嵌入式Redis的配置在RedissonAutoConfiguration之前加载,让Redis服务器先启动再初始化Redisson客户端。
方法1:使用@AutoConfigureBefore指定加载顺序
修改你的EmbeddedRedisConfiguration,加上@AutoConfigureBefore(RedissonAutoConfiguration.class),强制Spring先加载嵌入式Redis配置:
@Profile("test") @Configuration @AutoConfigureBefore(RedissonAutoConfiguration.class) // 确保此配置在Redisson之前加载 public class EmbeddedRedisConfiguration { private RedisServer redisServer; @Value("${spring.redis.port:6379}") private int redisPort; @PostConstruct public void startEmbeddedRedis() { // 启动嵌入式Redis服务器 redisServer = new RedisServer(redisPort); redisServer.start(); } @PreDestroy public void stopEmbeddedRedis() { if (redisServer != null) { redisServer.stop(); } } // 配置Redis连接工厂,供Spring Data Redis使用 @Bean public RedisConnectionFactory redisConnectionFactory() { return new LettuceConnectionFactory("localhost", redisPort); } }
方法2:动态设置Redis端口到环境变量
如果担心端口冲突,可以让嵌入式Redis随机启动端口,然后把实际端口注入到环境变量,让Redisson自动读取:
@Profile("test") @Configuration public class EmbeddedRedisConfiguration { private RedisServer redisServer; @PostConstruct public void startEmbeddedRedis() { // 随机端口启动Redis redisServer = RedisServer.builder().randomPort().build(); redisServer.start(); // 获取实际启动的端口 int actualPort = redisServer.getPort(); // 设置到环境变量,Redisson会读取spring.redis.port配置 System.setProperty("spring.redis.port", String.valueOf(actualPort)); } @PreDestroy public void stopEmbeddedRedis() { if (redisServer != null) { redisServer.stop(); } } }
方法3:用@DependsOn强制依赖顺序
如果你的Redisson配置是自定义Bean,可以给Redisson的Bean加上@DependsOn("redisServer"),确保Redis服务器Bean先初始化:
@Bean @DependsOn("redisServer") // 依赖嵌入式Redis的Bean public RedissonClient redissonClient() { Config config = new Config(); config.useSingleServer().setAddress("redis://localhost:" + redisPort); return Redisson.create(config); }
推荐优先尝试方案一 + 方法1的组合:用@AutoConfigureWebTestClient避免启动真实Web环境,同时用@AutoConfigureBefore确保Redis先启动,这样两个问题都能解决。
内容的提问来源于stack exchange,提问作者batboy

