Spring Reactive测试用例无法启动Netty Server问题排查
你的问题核心出在**测试依赖中的javax.servlet-api**上,具体原因如下:
当测试类的classpath中存在javax.servlet-api依赖时,Spring Boot的自动配置机制会检测到Servlet API的存在,从而默认尝试启动ServletWebServerApplicationContext(Servlet类型的Web上下文)。但你已经在主依赖中排除了Tomcat(Servlet容器),且没有引入其他Servlet容器,所以Spring找不到ServletWebServerFactory bean,就抛出了这个异常。
而你的主应用能正常启动Netty,是因为javax.servlet-api的scope是test——这个依赖只会在测试环境生效,主应用运行时的classpath里并没有它。此时Spring Boot会正确识别这是Reactive环境,自动启用Netty对应的ReactiveWebServerApplicationContext,所以主应用完全没问题。
1. 移除javax.servlet-api测试依赖
既然你是在测试Spring WebFlux的Reactive接口,完全不需要Servlet API依赖。直接从pom.xml中删除这段:
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>test</scope> </dependency>
移除后,测试环境的classpath里就没有Servlet API了,Spring Boot会自动切换到Reactive Web上下文,使用Netty启动,测试就能正常运行。
2. 优化测试类的WebTestClient配置
你的测试类里手动绑定WebTestClient的方式可以简化,推荐使用Spring Boot提供的自动配置注解:
@RunWith(SpringRunner.class) @SpringBootTest(classes = SpringWebFluxDemoApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @AutoConfigureWebTestClient // 自动配置WebTestClient public class CustomPriceControllerTest { @Autowired private WebTestClient testClient; // 直接注入即可 @Test public void broadcastVoltageConsumption() { this.testClient.get().uri("/api/getCustomPrice") .accept(MediaType.APPLICATION_STREAM_JSON) .exchange() .expectBodyList(Custom.class) .consumeWith(customResults -> { List<Custom> list = customResults.getResponseBody(); Assert.assertTrue(list != null && list.size() > 0); }); } }
这样既省去了手动初始化的代码,也能保证WebTestClient正确适配Reactive环境。
额外说明
如果之后你有部分测试需要用到Servlet环境(比如测试Spring MVC接口),可以单独给那些测试类添加javax.servlet-api依赖,或者使用@WebMvcTest这类专门针对Servlet MVC的测试注解,它会自动引入必要的Servlet相关依赖,不会影响其他Reactive测试。
内容的提问来源于stack exchange,提问作者Bilbo Baggins

