Spring WebFlux:如何用真实WebClient复现DataBufferLimitException?
可以用真实WebClient复现
DataBufferLimitException异常 完全可以用真实WebClient复现这个异常,之前出现WebClientRequestException(连接拒绝)是因为测试时没有启动对应的服务端来返回响应数据。只要在测试中搭建一个临时的服务端(返回指定大小的响应),再配合配置了小缓冲区的WebClient,就能精准复现场景。
实现步骤与示例代码
1. 搭建临时测试服务端
你可以通过两种方式快速搭建服务端:
方式一:使用Spring WebFlux测试切片(@WebFluxTest)
先定义一个测试用的Controller,返回指定大小的字节数据:
@RestController public class LargeResponseController { @GetMapping("/large-data") public Mono<DataBuffer> largeData(@RequestParam int size) { DataBuffer buffer = DefaultDataBufferFactory.sharedInstance.allocateBuffer(size); buffer.write(new byte[size]); return Mono.just(buffer); } }
然后编写测试类,启动这个Controller并配置小缓冲区的WebClient:
@WebFluxTest(LargeResponseController.class) class DataBufferLimitExceptionTest { @LocalServerPort private int port; private WebClient smallBufferWebClient; @BeforeEach void setUp() { // 配置仅1KB缓冲区的WebClient smallBufferWebClient = WebClient.builder() .baseUrl("http://localhost:" + port) .codecs(configurer -> configurer.defaultCodecs() .maxInMemorySize(1024 * 1)) // 对应你问题中的1024*bufferSize .build(); } @Test void whenResponseExceedsBuffer_throwsDataBufferLimitException() { // 请求1025字节的响应,超过缓冲区限制 Assertions.assertThrows(DataBufferLimitException.class, () -> { smallBufferWebClient.get() .uri("/large-data?size=1025") .retrieve() .bodyToMono(Void.class) .block(); }); } @Test void whenResponseWithinBuffer_returns200() { ResponseEntity<Void> response = smallBufferWebClient.get() .uri("/large-data?size=1024") .retrieve() .toBodilessEntity() .block(); Assertions.assertEquals(HttpStatus.OK, response.getStatusCode()); } }
方式二:手动启动Reactor Netty临时服务器
如果不想依赖Spring的测试上下文,可以直接用Reactor Netty搭建轻量服务端:
class DataBufferLimitExceptionManualTest { private HttpServer server; private String baseUrl; @BeforeEach void setUp() { // 启动随机端口的Netty服务器 server = HttpServer.create() .port(0) .route(routes -> routes .get("/large-data", (req, res) -> { int size = Integer.parseInt(req.param("size").orElse("0")); DataBuffer buffer = DefaultDataBufferFactory.sharedInstance.allocateBuffer(size); buffer.write(new byte[size]); return res.send(Mono.just(buffer)); })) .bindNow(); baseUrl = "http://localhost:" + server.port(); } @AfterEach void tearDown() { server.disposeNow(); // 测试结束关闭服务器 } @Test void testBufferLimitScenarios() { WebClient smallBufferWebClient = WebClient.builder() .baseUrl(baseUrl) .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(1024)) .build(); // 验证超限场景 Assertions.assertThrows(DataBufferLimitException.class, () -> { smallBufferWebClient.get() .uri("/large-data?size=1025") .retrieve() .bodyToMono(Void.class) .block(); }); // 验证正常场景 ResponseEntity<Void> okResponse = smallBufferWebClient.get() .uri("/large-data?size=512") .retrieve() .toBodilessEntity() .block(); Assertions.assertEquals(HttpStatus.OK, okResponse.getStatusCode()); } }
关键说明
- 连接拒绝问题的根源:测试时没有启动服务端,WebClient请求的地址无效。上述两种方式都会在测试生命周期内启动临时服务端,解决连接问题。
- 缓冲区配置:通过
maxInMemorySize设置WebClient的最大内存缓冲区,对应你问题中的1024*bufferSize,调整该值即可模拟不同的限制场景。
内容的提问来源于stack exchange,提问作者Maxim Kozlyuk
相关产品推荐
相关产品推荐

