如何在Spring Test的RestTemplate中保留application/json头发送非JSON请求
解决RestTemplate发送非JSON文本时自动修改Content-Type的问题
要模拟Content-Type: application/json但请求体为非JSON乱码文本的测试场景,核心是绕过RestTemplate默认消息转换器的自动ContentType覆盖逻辑,以下是两种实用方案:
方案一:自定义StringHttpMessageConverter强制支持application/json
RestTemplate默认的StringHttpMessageConverter仅支持text/plain等媒体类型,当你设置Content-Type: application/json并发送字符串请求体时,它会自动替换为text/plain。我们可以自定义转换器,让它支持application/json类型:
@ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class MalformedJsonInputTest { @Autowired private TestRestTemplate testRestTemplate; @Test void testMalformedJsonRequest() { // 自定义String转换器,仅支持application/json StringHttpMessageConverter customConverter = new StringHttpMessageConverter(); customConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON)); // 替换TestRestTemplate中的默认String转换器 RestTemplate restTemplate = testRestTemplate.getRestTemplate(); restTemplate.getMessageConverters().removeIf(c -> c instanceof StringHttpMessageConverter); restTemplate.getMessageConverters().add(customConverter); // 构造请求头与非JSON请求体 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); String malformedBody = "乱码或非JSON内容:@#$%^&*()_+"; HttpEntity<String> request = new HttpEntity<>(malformedBody, headers); // 发送请求并验证响应 ResponseEntity<String> response = restTemplate.exchange( "/api/your-target-endpoint", HttpMethod.POST, request, String.class ); assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); } }
方案二:使用字节数组作为请求体绕开自动转换
直接将字符串转为字节数组,借助ByteArrayHttpMessageConverter发送请求——这个转换器不会修改你手动设置的Content-Type,完全尊重自定义请求头:
@ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class MalformedJsonInputTest { @Autowired private TestRestTemplate testRestTemplate; @Test void testMalformedJsonWithByteArray() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); // 将非JSON文本转为字节数组 String malformedBody = "非JSON乱码:!@#$%^&*"; byte[] bodyBytes = malformedBody.getBytes(StandardCharsets.UTF_8); HttpEntity<byte[]> request = new HttpEntity<>(bodyBytes, headers); // 发送请求 ResponseEntity<String> response = testRestTemplate.exchange( "/api/your-target-endpoint", HttpMethod.POST, request, String.class ); assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); } }
关键原理
RestTemplate的消息转换器会根据请求体类型和配置的支持媒体类型自动调整Content-Type:
- 默认
StringHttpMessageConverter的支持列表不包含application/json,所以会强制替换为text/plain - 自定义转换器或使用字节数组,能避免这种自动替换,完全保留你设置的
application/json请求头,完美模拟curl发送的非法Schema请求场景
内容的提问来源于stack exchange,提问作者e-info128
相关产品推荐
相关产品推荐

