AHu*_*ist 18 java rest unit-testing web-services spring-mvc
好的,我有一个名为NamedSystems的类,它的唯一字段是一组NamedSystem.
我有一种方法可以通过某些标准找到NamedSystems.那不是很重要.当它得到结果时,一切正常.但是,当它找不到任何东西,从而返回null(或空 - 我已尝试过两种方式)设置时,我就会遇到问题.让我解释.
我正在使用Spring RestTemplate类,我在单元测试中进行这样的调用:
ResponseEntity<?> responseEntity = template.exchange(BASE_SERVICE_URL + "?
alias={aliasValue}&aliasAuthority={aliasAssigningAuthority}",
HttpMethod.GET, makeHttpEntity("xml"), NamedSystems.class,
alias1.getAlias(), alias1.getAuthority());
Run Code Online (Sandbox Code Playgroud)
现在,因为这通常会返回200,但我想返回204,我的服务中有一个拦截器,它确定ModelAndView是否是NamedSystem,如果它的集合为null.如果是,我然后将状态代码设置为NO_CONTENT(204).
当我运行junit测试时,我收到此错误:
org.springframework.web.client.RestClientException: Cannot extract response: no Content-Type found
Run Code Online (Sandbox Code Playgroud)
将状态设置为NO_CONTENT似乎擦除了内容类型字段(当我考虑它时这确实有意义).那为什么还要看呢?
Spring的HttpMessageConverterExtractor extractData方法:
public T extractData(ClientHttpResponse response) throws IOException {
MediaType contentType = response.getHeaders().getContentType();
if (contentType == null) {
throw new RestClientException("Cannot extract response: no Content-Type found");
}
for (HttpMessageConverter messageConverter : messageConverters) {
if (messageConverter.canRead(responseType, contentType)) {
if (logger.isDebugEnabled()) {
logger.debug("Reading [" + responseType.getName() + "] as \"" + contentType
+"\" using [" + messageConverter + "]");
}
return (T) messageConverter.read(this.responseType, response);
}
}
throw new RestClientException(
"Could not extract response: no suitable HttpMessageConverter found for response type [" +
this.responseType.getName() + "] and content type [" + contentType + "]");
}
Run Code Online (Sandbox Code Playgroud)
上一点链以找出Extractor的设置位置,我来看看我在测试中使用的RestTemplate的exchange()方法:
public <T> ResponseEntity<T> exchange(String url, HttpMethod method,
HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) throws RestClientException {
HttpEntityRequestCallback requestCallback = new HttpEntityRequestCallback(requestEntity, responseType);
ResponseEntityResponseExtractor<T> responseExtractor = new ResponseEntityResponseExtractor<T>(responseType);
return execute(url, method, requestCallback, responseExtractor, uriVariables);
}
Run Code Online (Sandbox Code Playgroud)
因此,由于交换调用提供的响应类型,它正在尝试将无效转换为什么.如果我将responseType从NamedSystems.class更改为null,它将按预期工作.它不会尝试转换任何东西.如果我试图将状态代码设置为404,它也可以正常执行.
我是误入歧途,还是看起来像RestTemplate中的一个缺陷?当然,我现在正在使用junit所以我知道会发生什么,但如果有人使用RestTemplate来调用它并且不知道服务调用的结果,他们自然会将NamedSystems作为响应类型.但是,如果他们尝试了没有元素的标准搜索,他们就会遇到这个令人讨厌的错误.
有没有办法解决这个问题而不重写任何RestTemplate的东西?我是否错误地查看了这种情况?请帮忙,因为我有点困惑.
Cha*_*dra 12
解决此问题的另一种方法是将响应实体设为null,如下所示.
Run Code Online (Sandbox Code Playgroud)ResponseEntity<?> response = restTemplate.exchange("http://localhost:8080/myapp/user/{userID}", HttpMethod.DELETE, requestEntity, null, userID);
如果仍需要响应头,请尝试实现ResponseErrorHandler.
Dav*_*tor 10
我相信您应该查看ResponseExtractor接口并在RestTemplate上调用execute,提供您的提取器实现.对我来说,这似乎是一个常见的要求,所以记录了这个:
https://jira.springsource.org/browse/SPR-8016
这是我之前准备的一个:
private class MyResponseExtractor extends HttpMessageConverterExtractor<MyEntity> {
public MyResponseExtractor (Class<MyEntity> responseType,
List<HttpMessageConverter<?>> messageConverters) {
super(responseType, messageConverters);
}
@Override
public MyEntity extractData(ClientHttpResponse response) throws IOException {
MyEntity result;
if (response.getStatusCode() == HttpStatus.OK) {
result = super.extractData(response);
} else {
result = null;
}
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
我已经测试了这个,它似乎做了我想要的.
要创建ResponseExtractor的实例,我调用构造函数并从已注入的RestTemplate实例传递转换器;
例如
ResponseExtractor<MyEntity> responseExtractor =
new MyResponseExtractor(MyEntity.class, restTemplate.getMessageConverters());
Run Code Online (Sandbox Code Playgroud)
然后电话是:
MyEntity responseAsEntity =
restTemplate.execute(urlToCall, HttpMethod.GET, null, responseExtractor);
Run Code Online (Sandbox Code Playgroud)
你的旅费可能会改变.;-)
这是一个简单的解决方案,您可以设置默认的Content-Type,以便在响应中缺少时使用.在将Content-Type传递回预先配置的ResponseExtractor以进行提取之前,它将添加到响应标头中.
public class CustomRestTemplate extends RestTemplate {
private MediaType defaultResponseContentType;
public CustomRestTemplate() {
super();
}
public CustomRestTemplate(ClientHttpRequestFactory requestFactory) {
super(requestFactory);
}
public void setDefaultResponseContentType(String defaultResponseContentType) {
this.defaultResponseContentType = MediaType.parseMediaType(defaultResponseContentType);
}
@Override
protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, final ResponseExtractor<T> responseExtractor)
throws RestClientException {
return super.doExecute(url, method, requestCallback, new ResponseExtractor<T>() {
public T extractData(ClientHttpResponse response) throws IOException {
if (response.getHeaders().getContentType() == null && defaultResponseContentType != null) {
response.getHeaders().setContentType(defaultResponseContentType);
}
return responseExtractor.extractData(response);
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
67078 次 |
| 最近记录: |