SpringBoot 3中TestRestTemplate调用返回400接口时触发I/O错误
问题解决:TestRestTemplate调用返回400接口时抛出I/O错误
这个错误的核心原因是默认TestRestTemplate底层的HttpClient重试机制与流式请求(如JSON POST体)冲突:当服务器返回400时,HttpClient尝试重试请求,但因为请求体已经被流式发送,无法重复读取,从而抛出该异常。
解决方案1:自定义TestRestTemplate,禁用重试策略
通过RestTemplateBuilder构建自定义的TestRestTemplate,关闭重试机制:
import org.springframework.boot.test.web.client.TestRestTemplate import org.springframework.boot.web.client.RestTemplateBuilder import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Primary import org.springframework.http.client.SimpleClientHttpRequestFactory @Bean @Primary fun testRestTemplate(builder: RestTemplateBuilder): TestRestTemplate { val requestFactory = SimpleClientHttpRequestFactory().apply { setConnectTimeout(5000) setReadTimeout(5000) } return TestRestTemplate(builder.requestFactory { requestFactory }.build()) }
解决方案2:改用exchange方法替代postForEntity
exchange方法对响应的处理更灵活,能避免重试触发的问题:
@Test fun signIn_InvalidPassword() { val headers = HttpHeaders() headers.contentType = MediaType.APPLICATION_JSON val body = AuthenticationRequest(email = "user@email.com", password = "password") val httpRequest: HttpEntity<AuthenticationRequest> = HttpEntity(body, headers) val result = testRestTemplate.exchange( "/auth/signin", HttpMethod.POST, httpRequest, String::class.java ) assertThat(result.statusCode, equalTo(HttpStatus.BAD_REQUEST)) }
解决方案3:调整响应解析方式
如果服务返回的400响应包含JSON格式的错误信息,可以直接指定对应的错误DTO类作为响应类型,而非String::class.java,这也能避免流式读取的重试冲突:
// 假设你的错误响应DTO类是ValidationErrorResponse val result = testRestTemplate.postForEntity( "/auth/signin", httpRequest, ValidationErrorResponse::class.java )
内容的提问来源于stack exchange,提问作者Panos
相关产品推荐
相关产品推荐

