Spring Boot Webflux测试中WebTestClient如何正确解析String[]响应
问题原因
这个问题的根源是WebTestClient的默认编解码器匹配逻辑:
- 调用
expectBodyList(String.class)时,客户端会优先匹配纯字符串解码器,这个解码器不会做JSON结构解析,直接把整个响应体内容(也就是接口返回的完整JSON数组字符串["Fruits","Regional"])作为单个字符串元素存入列表,最终你拿到的就是长度为1、内容是完整JSON串的列表。 - 你同时引入了Servlet栈的
spring-boot-starter-web和响应式栈的spring-boot-starter-webflux,Spring Boot在这种混合栈场景下自动配置的WebTestClient不会自动为String类型目标启用JSON反序列化逻辑。Postman直接调用能看到正常数组是因为Postman会自动对响应做JSON格式化展示,和客户端的解码逻辑无关。
解决方案
两种方案任选即可,优先推荐第一种:
方案1:明确指定泛型类型触发JSON反序列化
不要直接传String.class作为列表元素类型,用ParameterizedTypeReference明确声明目标类型为List<String>,强制WebTestClient调用Jackson JSON解码器解析响应结构。
修改后的测试代码逻辑如下:
import org.springframework.core.ParameterizedTypeReference; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.reactive.server.WebTestClient; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class StackOverFlowControllerTest { @Autowired WebTestClient webTestClient; @Test void whenListOfStringsEndpoint_thenExpectListOfStrings(){ List<String> actual = webTestClient.get() .uri("/allBoxes") .exchange() .expectStatus().is2xxSuccessful() .expectBody(new ParameterizedTypeReference<List<String>>() {}) .returnResult() .getResponseBody(); assertEquals(List.of("Fruits", "Regional"), actual); } }
这种写法会明确告诉WebTestClient需要把响应解析成字符串列表,JSON解码器会自动把数组拆成两个独立的字符串元素,断言就能正常通过。
方案2:自定义WebTestClient编解码器配置
如果你想保留expectBodyList(String.class)的写法,可以手动初始化WebTestClient,调整编解码器的优先级,让JSON解码器优先处理字符串类型响应:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class StackOverFlowControllerTest { private WebTestClient webTestClient; @Autowired void initWebTestClient(ApplicationContext context) { this.webTestClient = WebTestClient.bindToApplicationContext(context) .configureClient() .codecs(config -> config.defaultCodecs().maxInMemorySize(16 * 1024 * 1024)) .build(); } // 原有测试方法无需修改 }
这种方式灵活性更高,但类型声明不如方案1清晰,后续维护时容易因为编解码器配置变动出现非预期行为。
补充建议
如果你的项目是纯Spring MVC(Servlet栈)应用,没有实际使用WebFlux的响应式能力,测试Web层更推荐使用MockMvc,可以完全避免两种Web栈混合带来的默认配置差异问题,只需要添加@AutoConfigureMockMvc注解,注入MockMvc实例发起请求即可。
内容的提问来源于stack exchange,提问作者slartidan
相关产品推荐
相关产品推荐

