Java 使用 @ControllerAdvice 测试 @RestController
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24765219/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Testing @RestController with @ControllerAdvice
提问by tep
My problem is connected with testing Spring @RestController which is also using @ControllerAdvice with @ExceptionHandler. Here is the code:
我的问题与测试 Spring @RestController 相关,它也将 @ControllerAdvice 与 @ExceptionHandler 一起使用。这是代码:
@ControllerAdvice class:
@ControllerAdvice 类:
@ControllerAdvice
public class MyAppExceptionHandler {
@ExceptionHandler({ NoSuchEntityException.class })
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public @ResponseBody
ErrorDTO handleNotFoundException(Exception ex) throws IOException {
return new ErrorDTO.Builder().setStatus(HttpStatus.NOT_FOUND)
.setCause(ex.getClass().getName())
.setThrowable(ex).build();
}
}
When using it in application everything works fine - perfectly getting 404 response with JSON explanation, but when trying to use it during tests - bad things happen.
在应用程序中使用它时一切正常 - 完美地获得带有 JSON 解释的 404 响应,但是在测试期间尝试使用它时 - 会发生不好的事情。
My test class:
我的测试班:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { WebConfig.class })
@WebAppConfiguration
public class SomeTest {
@Mock
private SomeService service;
@InjectMocks
private SomeController controller;
private MockMvc mvc;
private ExceptionHandlerExceptionResolver createExceptionResolver() {
ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() {
@Override
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(
HandlerMethod handlerMethod, Exception exception) {
Method method = new ExceptionHandlerMethodResolver(
MyAppExceptionHandler.class).resolveMethod(exception);
return new ServletInvocableHandlerMethod(
new MyAppExceptionHandler(), method);
}
};
exceptionResolver.afterPropertiesSet();
return exceptionResolver;
}
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(controller)
.setHandlerExceptionResolvers(createExceptionResolver())
.build();
}
@Test
public void thatExceptionHappens() throws Exception {
when(service.get(10)).thenThrow(new NoSuchEntityException(Some.class, 10));
mvc.perform(get("/api/some/10")).andExpect(status().isNotFound());
}
}
When trying to run it:
尝试运行时:
2014-07-15 19:35:01.376 [main] ERROR com.package.SomeTest - Failed to invoke @ExceptionHandler method: public com.package.ErrorDTO com.package.MyAppExceptionHandler.handleNotFoundException(java.lang.Exception) throws java.io.IOException
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
I think that probably MappingHymanson2HttpMessageConverter is not being loaded during testing mine @ExceptionHandler (however it is configured in WebConfig.class and when trying to perform typical test - one not throwing any exception - everything works fine).
我认为可能 MappingHymanson2HttpMessageConverter 在测试我的 @ExceptionHandler 期间没有被加载(但是它是在 WebConfig.class 中配置的,并且在尝试执行典型测试时 - 没有抛出任何异常 - 一切正常)。
Thanks in advance for your help.
在此先感谢您的帮助。
采纳答案by Denis C de Azevedo
I'm not sure if this is the best solution for this (I'd like to hear from another one),
but this is how I fix this exactly issue you are facing:
我不确定这是否是最好的解决方案(我想听听另一个人的意见),
但这就是我解决您所面临的确切问题的方法:
Add this line to your createExceptionResolver()
:
将此行添加到您的createExceptionResolver()
:
exceptionResolver.getMessageConverters().add(
new MappingHymanson2HttpMessageConverter());
Something like this:
像这样的东西:
private ExceptionHandlerExceptionResolver createExceptionResolver() {
ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() {
@Override
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(
HandlerMethod handlerMethod, Exception exception) {
Method method = new ExceptionHandlerMethodResolver(
MyAppExceptionHandler.class).resolveMethod(exception);
return new ServletInvocableHandlerMethod(
new MyAppExceptionHandler(), method);
}
};
exceptionResolver.getMessageConverters().add(new MappingHymanson2HttpMessageConverter());
exceptionResolver.afterPropertiesSet();
return exceptionResolver;
}
For some reason that I don't know, Spring was not loading my MappingHymanson2HttpMessageConverter.
That line fixed my problem.
出于某种我不知道的原因,Spring 没有加载我的MappingHymanson2HttpMessageConverter。
那条线解决了我的问题。
回答by Rossen Stoyanchev
The MockMvcBuilders standaloneSetup is manual by definition meaning that rather than discovering Spring beans of interest like @ControllerAdvice in Spring configuration, it lets you manually set up what you need for the test. Instead the standaloneSetup should let you also manually register @ControllerAdvice beans. There is a ticket for making that happen. See https://jira.spring.io/browse/SPR-12751.
MockMvcBuilders standaloneSetup 根据定义是手动的,这意味着它不是在 Spring 配置中发现像 @ControllerAdvice 这样感兴趣的 Spring bean,而是让您手动设置测试所需的内容。相反,standaloneSetup 应该让您也手动注册@ControllerAdvice bean。有一张票可以做到这一点。请参阅https://jira.spring.io/browse/SPR-12751。