无法正确测试 ErrorController Spring 引导
Cannot properly test ErrorController Spring Boot
由于本教程 - https://www.baeldung.com/spring-boot-custom-error-page 我想自定义我的错误页面,即。当有人去 www.myweb.com/blablablalb3
我想 return 带有文本 "wrong url request" 的页面时。
一切正常:
@Controller
public class ApiServerErrorController implements ErrorController {
@Override
public String getErrorPath() {
return "error";
}
@RequestMapping("/error")
public String handleError() {
return "forward:/error-page.html";
}
}
但是我不知道怎么测试:
@Test
public void makeRandomRequest__shouldReturnErrorPage() throws Exception {
this.mockMvc.perform(get(RANDOM_URL))
.andDo(print());
}
打印() returns:
MockHttpServletResponse:
Status = 404
Error message = null
Headers = {X-Application-Context=[application:integration:-1]}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
所以我不能创建这样的东西:
.andExpect(forwardedUrl("error-page"));
因为它失败了,但是在手动测试中错误页面是 returned。
不幸的是,不支持使用 MockMvc
测试自定义 ErrorController
。
详细解释见Spring Boot team(source)的官方推荐。
To be sure that any error handling is working fully, it's necessary to
involve the servlet container in that testing as it's responsible for
error page registration etc. Even if MockMvc itself or a Boot
enhancement to MockMvc allowed forwarding to an error page, you'd be
testing the testing infrastructure not the real-world scenario that
you're actually interested in.
Our recommendation for tests that want to be sure that error handling
is working correctly, is to use an embedded container and test with
WebTestClient, RestAssured, or TestRestTemplate.
我的建议是使用@ControllerAdvice
通过这种方式,您可以解决该问题,并且可以继续使用 MockMvc,其最大优势是您不需要 运行 服务器。
当然,要显式测试错误页面管理,您需要 运行 服务器。我的建议主要是针对那些已经实现了ErrorController但仍然想使用MockMvc进行单元测试的人。
@ControllerAdvice
public class MyControllerAdvice {
@ExceptionHandler(FileSizeLimitExceededException.class)
public ResponseEntity<Throwable> handleFileException(HttpServletRequest request, FileSizeLimitExceededException ex) {
return new ResponseEntity<>(ex, HttpStatus.PAYLOAD_TOO_LARGE);
}
@ExceptionHandler(Throwable.class)
public ResponseEntity<Throwable> handleUnexpected(HttpServletRequest request, Throwable throwable) {
return new ResponseEntity<>(throwable, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
由于本教程 - https://www.baeldung.com/spring-boot-custom-error-page 我想自定义我的错误页面,即。当有人去 www.myweb.com/blablablalb3
我想 return 带有文本 "wrong url request" 的页面时。
一切正常:
@Controller
public class ApiServerErrorController implements ErrorController {
@Override
public String getErrorPath() {
return "error";
}
@RequestMapping("/error")
public String handleError() {
return "forward:/error-page.html";
}
}
但是我不知道怎么测试:
@Test
public void makeRandomRequest__shouldReturnErrorPage() throws Exception {
this.mockMvc.perform(get(RANDOM_URL))
.andDo(print());
}
打印() returns:
MockHttpServletResponse:
Status = 404
Error message = null
Headers = {X-Application-Context=[application:integration:-1]}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
所以我不能创建这样的东西:
.andExpect(forwardedUrl("error-page"));
因为它失败了,但是在手动测试中错误页面是 returned。
不幸的是,不支持使用 MockMvc
测试自定义 ErrorController
。
详细解释见Spring Boot team(source)的官方推荐。
To be sure that any error handling is working fully, it's necessary to involve the servlet container in that testing as it's responsible for error page registration etc. Even if MockMvc itself or a Boot enhancement to MockMvc allowed forwarding to an error page, you'd be testing the testing infrastructure not the real-world scenario that you're actually interested in.
Our recommendation for tests that want to be sure that error handling is working correctly, is to use an embedded container and test with WebTestClient, RestAssured, or TestRestTemplate.
我的建议是使用@ControllerAdvice
通过这种方式,您可以解决该问题,并且可以继续使用 MockMvc,其最大优势是您不需要 运行 服务器。
当然,要显式测试错误页面管理,您需要 运行 服务器。我的建议主要是针对那些已经实现了ErrorController但仍然想使用MockMvc进行单元测试的人。
@ControllerAdvice
public class MyControllerAdvice {
@ExceptionHandler(FileSizeLimitExceededException.class)
public ResponseEntity<Throwable> handleFileException(HttpServletRequest request, FileSizeLimitExceededException ex) {
return new ResponseEntity<>(ex, HttpStatus.PAYLOAD_TOO_LARGE);
}
@ExceptionHandler(Throwable.class)
public ResponseEntity<Throwable> handleUnexpected(HttpServletRequest request, Throwable throwable) {
return new ResponseEntity<>(throwable, HttpStatus.INTERNAL_SERVER_ERROR);
}
}