使用 Spring Boot TestRestTemplate 相对路径强制 JSON 转换



根据 Spring Boot 文档:

请注意,TestRestTemplate现在只要 使用@SpringBootTest。它已预先配置为解析相对路径 到http://localhost:${local.server.port}.我们也可以使用 @LocalServerPort注释以注入服务器的实际端口 正在运行到测试领域。

我有一个返回 XML 数据的 RESTFul 应用程序。该POM文件包含jackson-dataformat-xml 在测试类中,我有以下代码:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class XMLDataTest {
    @Autowired
    private TestRestTemplate restTemplate;
    ...
    ResponseEntity<List<City>> cities = restTemplate.exchange(appPath,
        HttpMethod.GET, null, paramType);
    assertThat(cities.getBody()).hasSize(8);
    assertThat(cities.getBody()).contains(this.c1, this.c2, this.c3);

如果appPath等于完整 URL,例如 http://localhost:9234/myapp/cities ,则测试运行正常。如果appPath等于相对路径,/myapp/cities,我得到一个 JSON 异常。看起来相对路径强制 JSON 转换。

例外:

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
 at [Source: java.io.PushbackInputStream@4628a02b; line: 1, column: 1]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270)
    at com.fasterxml.jackson.databind.DeserializationContext.reportMappingException(DeserializationContext.java:1234)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1122)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1075)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.handleNonArray(CollectionDeserializer.java:338)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:269)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:259)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:26)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3814)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2938)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:235)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:223)
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:96)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:924)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:908)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:662)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:620)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:566)
    at org.springframework.boot.test.web.client.TestRestTemplate.exchange(TestRestTemplate.java:812)
    at com.zetcode.test.RestControllerTest.allCitiesTest(RestControllerTest.java:51)

如何解决这个问题?

API 返回一个 JSON 对象,而您需要一个 JSON 数组,因此会出现异常。若要使其返回 XML,需要指定请求的"接受"标头。

有用的技巧:调试此类问题时,使用 String.class 作为预期的响应类型,并打印结果。

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity<String> entity = new HttpEntity<>("parameters", headers);
ResponseEntity<List<City>> cities = restTemplate.exchange(appPath,
           HttpMethod.GET, entity, paramType);

相关内容

  • 没有找到相关文章

最新更新