使用SpringMVC测试测试SpringMVC@ExceptionHandler方法
我有以下简单的控制器来捕获任何意外的异常:使用SpringMVC测试测试SpringMVC@ExceptionHandler方法,spring,spring-mvc,mockito,spring-mvc-test,Spring,Spring Mvc,Mockito,Spring Mvc Test,我有以下简单的控制器来捕获任何意外的异常: @ControllerAdvice public class ExceptionController { @ExceptionHandler(Throwable.class) @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) @ResponseBody public ResponseEntity handleException(Throwable ex)
@ControllerAdvice
public class ExceptionController {
@ExceptionHandler(Throwable.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResponseEntity handleException(Throwable ex) {
return ResponseEntityFactory.internalServerErrorResponse("Unexpected error has occurred.", ex);
}
}
我正在尝试使用SpringMVC测试框架编写一个集成测试。这就是我到目前为止所做的:
@RunWith(MockitoJUnitRunner.class)
public class ExceptionControllerTest {
private MockMvc mockMvc;
@Mock
private StatusController statusController;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new ExceptionController(), statusController).build();
}
@Test
public void checkUnexpectedExceptionsAreCaughtAndStatusCode500IsReturnedInResponse() throws Exception {
when(statusController.checkHealth()).thenThrow(new RuntimeException("Unexpected Exception"));
mockMvc.perform(get("/api/status"))
.andDo(print())
.andExpect(status().isInternalServerError())
.andExpect(jsonPath("$.error").value("Unexpected Exception"));
}
}
我在SpringMVC基础设施中注册ExceptionController和模拟StatusController。
在测试方法中,我设置了从StatusController引发异常的期望
正在抛出异常,但ExceptionController没有处理它
我希望能够测试ExceptionController是否获取异常并返回适当的响应
你有没有想过为什么这样不行,我应该怎么做这种测试
谢谢。由于您使用的是单机安装测试,因此需要手动提供异常处理程序
mockMvc= MockMvcBuilders.standaloneSetup(adminCategoryController).setSingleView(view)
.setHandlerExceptionResolvers(getSimpleMappingExceptionResolver()).build();
几天前我也遇到过同样的问题,你可以在这里看到我的问题和解决方案
希望我的回答能帮助你试试看
@RunWith(value = SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = { MVCConfig.class, CoreConfig.class,
PopulaterConfiguration.class })
public class ExceptionControllerTest {
private MockMvc mockMvc;
@Mock
private StatusController statusController;
@Autowired
private WebApplicationContext wac;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void checkUnexpectedExceptionsAreCaughtAndStatusCode500IsReturnedInResponse() throws Exception {
when(statusController.checkHealth()).thenThrow(new RuntimeException("Unexpected Exception"));
mockMvc.perform(get("/api/status"))
.andDo(print())
.andExpect(status().isInternalServerError())
.andExpect(jsonPath("$.error").value("Unexpected Exception"));
}
}
此代码将添加使用异常控制建议的功能
@Before
public void setup() {
this.mockMvc = standaloneSetup(commandsController)
.setHandlerExceptionResolvers(withExceptionControllerAdvice())
.setMessageConverters(new MappingJackson2HttpMessageConverter()).build();
}
private ExceptionHandlerExceptionResolver withExceptionControllerAdvice() {
final ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() {
@Override
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(final HandlerMethod handlerMethod,
final Exception exception) {
Method method = new ExceptionHandlerMethodResolver(ExceptionController.class).resolveMethod(exception);
if (method != null) {
return new ServletInvocableHandlerMethod(new ExceptionController(), method);
}
return super.getExceptionHandlerMethod(handlerMethod, exception);
}
};
exceptionResolver.afterPropertiesSet();
return exceptionResolver;
}
我也有同样的问题,我的作品如下:
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(statusController)
.setControllerAdvice(new ExceptionController())
.build();
}
这样更好:
((HandlerExceptionResolverComposite) wac.getBean("handlerExceptionResolver")).getExceptionResolvers().get(0)
不要忘记在@Configuration类中扫描@ControllerAdvice bean:
@ComponentScan(basePackages = {"com.company.exception"})
…在Spring 4.0.2上测试。发布版使用Spring MockMVC模拟servletContainer,使您可以将任何请求过滤或异常处理测试合并到单元测试套件中 您可以使用以下方法配置此设置: 给定自定义RecordNotFound异常
@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Record not found") //
public class RecordNotFoundException extends RuntimeException {
private static final long serialVersionUID = 8857378116992711720L;
public RecordNotFoundException() {
super();
}
public RecordNotFoundException(String message) {
super(message);
}
}
。。。和RecordNotFoundExceptionHandler
@Slf4j
@ControllerAdvice
public class BusinessExceptionHandler {
@ExceptionHandler(value = RecordNotFoundException.class)
public ResponseEntity<String> handleRecordNotFoundException(
RecordNotFoundException e,
WebRequest request) {
//Logs
LogError logging = new LogError("RecordNotFoundException",
HttpStatus.NOT_FOUND,
request.getDescription(true));
log.info(logging.toJson());
//Http error message
HttpErrorResponse response = new HttpErrorResponse(logging.getStatus(), e.getMessage());
return new ResponseEntity<>(response.toJson(),
HeaderFactory.getErrorHeaders(),
response.getStatus());
}
...
}
配置模拟MVC“servlet emulator”:在上下文中注册处理程序bean并构建模拟MVC emulator(注意:有两种可能的配置:standaloneSetup或webAppContextSetup;请参阅)。生成器正确地实现了生成器模式,因此您可以在调用build()之前为异常解析程序和处理程序链接配置命令
获取异常解析程序
private ExceptionHandlerExceptionResolver getExceptionResolver(
StaticApplicationContext context) {
ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver();
resolver.getMessageConverters().add(
new MappingJackson2HttpMessageConverter());
resolver.setApplicationContext(context);
resolver.afterPropertiesSet();
return resolver;
}
运行您的测试
@Test
public void testGetSingleOrganisationRecordAnd404() throws Exception {
System.out.println("testGetSingleOrganisationRecordAndSuccess");
String request = "/orgs/{id}";
log.info("Request URL: " + request);
when(service.getOrganisation(anyString())).
thenReturn(coorg);
this.mvc.perform(get(request)
.accept("application/json")
.andExpect(content().contentType(
.APPLICATION_JSON))
.andExpect(status().notFound())
.andDo(print());
}
....
}
希望这有帮助
杰克。我也有同样的问题;这对我很有用: *thenThrow()中的运行时异常;ErrorHandler不会捕获异常或可丢弃的父类。
*删除正在测试的方法的所有try-catch语句
*根本不需要@Before或@ComponentScan注释
when(getRejectionQuery.execute(anyInt(), anyInt(), anyMap())).thenThrow(new RuntimeException());
我猜在测试中,异常处理程序没有被分配,不知道确切的原因,但这就是它发生的原因,看看这个答案,有什么消息吗?我也遇到了同样的情况,我没有找到解决办法。我决定相信@ExceptionHandler是有效的,因为方法本身很简单,所以我决定不用测试注释就可以生存。您仍然可以使用常规的单元测试来测试该方法。您的异常可能扩展了Throwable而不是exception。我遇到了同样的问题,并检查了InvocableHandlerMethod中的代码,该方法检查以下
else if(targetException instanceof Exception){throw(Exception)targetException;}
检查解决方案是否有帮助。将$.error替换为$.Message代码中包含getExceptionResolver()函数的包是什么?@Dhana解析了缺少的解析器getter。谢谢你升旗。
@Test
public void testGetSingleOrganisationRecordAnd404() throws Exception {
System.out.println("testGetSingleOrganisationRecordAndSuccess");
String request = "/orgs/{id}";
log.info("Request URL: " + request);
when(service.getOrganisation(anyString())).
thenReturn(coorg);
this.mvc.perform(get(request)
.accept("application/json")
.andExpect(content().contentType(
.APPLICATION_JSON))
.andExpect(status().notFound())
.andDo(print());
}
....
}
when(getRejectionQuery.execute(anyInt(), anyInt(), anyMap())).thenThrow(new RuntimeException());