【发布时间】:2019-10-13 02:52:27
【问题描述】:
我有一个全局异常处理程序如下:-
@ControllerAdvice
@RestController
public class GlobalExceptionHandler {
@ExceptionHandler(value= {HttpMessageNotReadableException.class})
public final ResponseEntity<ErrorDetails> validationException(HttpMessageNotReadableException ex, WebRequest request) {
System.out.println("This was called.");
if(ex.getCause() instanceof CsvRequiredFieldEmptyException){
CsvRequiredFieldEmptyException csvExp = (CsvRequiredFieldEmptyException) ex.getCause();
String exceptionDtls = csvExp.getMessage().concat(" ").concat(" at line number "+csvExp.getLineNumber()+ " in the csv filw.");
ErrorDetails errorDetails = new ErrorDetails(LocalDate.now(),exceptionDtls, request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
}
}
我正在使用 TestRestTemplate 调用其余 API 进行集成测试。
ResponseEntity<?> response = restTemplate.exchange(ITestUtils.createURLWithPort(postUrlCsv,
host,port ), HttpMethod.POST,listingDocEnt, String.class);
@Test
public void uploadListingCsvTest_Returns400BadReq_WhenCodeMissing() throws HttpMessageNotReadableException {
// Step 1 : Create the Http entity object which contains the request body and headers.
HttpEntity<ListingList> listingDocEnt = new HttpEntity<ListingList>(createTestDataForNewVehicleListingCodeMissing(),
getHttpHeaderCsv());
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
List<HttpMessageConverter<?>> csvMessgeonverter = new ArrayList<>();
csvMessgeonverter.add(new CsvHttpMessageConverter<>());
csvMessgeonverter.add(converter);
TestRestTemplate restTemplate = new TestRestTemplate();
restTemplate.getRestTemplate().setMessageConverters(csvMessgeonverter);
ResponseEntity<?> response = restTemplate.exchange(ITestUtils.createURLWithPort(postUrlCsv,
host,port ), HttpMethod.POST,listingDocEnt, String.class);
// Check if the response is not null and the http status code is - 201 Created.
Assert.assertNotNull(response);
Assert.assertEquals(HttpStatus.BAD_REQUEST,response.getStatusCode());
}
我的 rest API 有自定义的 HttpMessageConverter,如下所示,它将输入请求 csv 转换为 rest 控制器中的 java 对象。这个自定义消息转换器有一个 readInternal 方法,它抛出一个异常 HttpMessageNotReadableException ,但仍然没有调用异常处理程序方法“validationException”。 Junit 只是简单地坏掉了。
public class CsvHttpMessageConverter<T, L extends ListParam<T>>
extends AbstractHttpMessageConverter<L> {
public CsvHttpMessageConverter () {
super(new MediaType("text", "csv"));
}
@Override
protected boolean supports (Class<?> clazz) {
return ListParam.class.isAssignableFrom(clazz);
}
@Override
protected L readInternal (Class<? extends L> clazz,HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<>();
Class<T> t = toBeanType(clazz.getGenericSuperclass());
strategy.setType(t);
CSVReader csv = new CSVReader(new InputStreamReader(inputMessage.getBody()));
CsvToBean<T> csvToBean = new CsvToBean<>();
List<T> beanList = null;
try {
beanList = csvToBean.parse(strategy, csv);
} catch(Exception exception){
throw new HttpMessageNotReadableException("Exception while parsing the CSV file.",exception.getCause());
}
try {
L l = clazz.newInstance();
l.setList(beanList);
return l;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
@Override
protected void writeInternal (L l, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<>();
strategy.setType(toBeanType(l.getClass().getGenericSuperclass()));
OutputStreamWriter outputStream = new OutputStreamWriter(outputMessage.getBody());
StatefulBeanToCsv<T> beanToCsv =
new StatefulBeanToCsvBuilder(outputStream)
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.withMappingStrategy(strategy)
.build();
try {
beanToCsv.write(l.getList());
} catch (CsvDataTypeMismatchException e) {
throw new HttpMessageNotWritableException("Exception while parsing the CSV file.",e);
} catch (CsvRequiredFieldEmptyException e) {
throw new HttpMessageNotWritableException("Exception while parsing the CSV file.",e);
}
outputStream.close();
}
@SuppressWarnings("unchecked")
private Class<T> toBeanType (Type type) {
return (Class<T>) ((ParameterizedType) type).getActualTypeArguments()[0];
}
有没有办法在使用 TestRestTemplate 调用 Spring Rest API 时,在出现异常时调用异常处理程序方法?
【问题讨论】:
-
你的方法也应该从你使用restTemplate的地方抛出HttpMessageNotReadableException。
-
您能详细说明一下吗?我的 rest API 方法抛出 HttpMessageNotReadableException 异常,但它没有被 @Exception 处理程序中存在的 validationException 方法捕获 - 这就是问题所在。
-
提供你提到的方法restTemplate.exchange ...代码
-
我用实际的@Test junit 方法编辑了上面的帖子。请看一看。
-
尝试将请求放在第一个参数中? public final ResponseEntity
validationException(WebRequest request, HttpMessageNotReadableException ex)
标签: java rest spring-boot spring-test