如何使用junit在spring-boot中测试常见错误ErrorController
Posted
技术标签:
【中文标题】如何使用junit在spring-boot中测试常见错误ErrorController【英文标题】:How to test common error ErrorController in spring-boot with junit 【发布时间】:2017-08-03 07:52:58 【问题描述】:在一个 Spring Boot 项目中,我想用 Junit 测试我的 ErrorController。 代码如下sn-p。
@RestController
public class ApiErrorController implements ErrorController
private static final Logger LOGGER = LoggerFactory.getLogger(ApiErrorController.class);
@Value("$server.error.path")
private String errorPath;
@Override
public String getErrorPath()
return this.errorPath;
@RequestMapping("/error")
public ResponseEntity<ErrorResult> error(HttpServletRequest request, HttpServletResponse response)
String requestURI = (String) request.getAttribute("javax.servlet.forward.request_uri");
LOGGER.info("error handling start url = ", requestURI);
String servletMessage = (String) request.getAttribute("javax.servlet.error.message");
Integer servletStatus = (Integer) request.getAttribute("javax.servlet.error.status_code");
String[] messages = new String[0];
if (!StringUtils.isNullOrEmpty(servletMessage))
messages = new String[] servletMessage ;
HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
try
if (servletStatus != null && servletStatus instanceof Integer)
status = HttpStatus.valueOf(servletStatus);
catch (Exception ex) // test this exception
LOGGER.warn("http status not converted.", request.getAttribute("javax.servlet.error.status_code"), ex);
ErrorResult body = new ErrorResult();
body.setMessages(messages);
ResponseEntity<ErrorResult> responseResult = new ResponseEntity<>(body, status);
return responseResult;
当我的 Controller(例如 AbcController)发生业务异常时,程序进入 ExceptionControllerAdvice 类。 如果 ExceptionControllerAdvice 发生异常,则程序进入上述 ApiErrorController 类。
有人能告诉我如何测试HttpStatus.valueOf(servletStatus)
失败的情况吗?
另外,我希望request.getAttribute("javax.servlet.error.message")
返回一个非空字符串。
如何实现我想测试的?
顺便说一下,我不想只测试error
方法的逻辑。我想使用我提到的AbcController
进行测试。我想要的是当AbcController
发生错误时,那么ApiErrorController
中的error
方法可以成功处理。
追加:
比如ExceptionControllerAdvice
会处理业务异常。
@ControllerAdvice(annotations = RestController.class)
public class ExceptionControllerAdvice
private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionControllerAdvice.class);
@ExceptionHandler( BusinessCloudException.class )
public ResponseEntity<ErrorResult> handleBlCloudException(HttpServletRequest request, HttpServletResponse response,
BlCloudException ex)
HttpStatus status = ErrorUtils.toHttpStatus(ex.getType());
ErrorResult body = new ErrorResult();
body.setMessages(ex.getMessageArray());
ResponseEntity<ErrorResult> responseResult = new ResponseEntity<>(body, status);
return responseResult;
如果handleBlCloudException
方法发生错误,则程序进入ApiErrorController
处理该错误。
程序如何生成特定的servletStatus
和javax.servlet.error.message
?如何模拟来做到这一点?
【问题讨论】:
【参考方案1】:首先,该错误方法发生了很多事情。您可能会考虑将一些逻辑转移到专门的类/公共方法中。
除此之外,我建议使用 Mockito。
首先创建一个封装HttpStatus检索的方法:
HttpStatus getHttpStatusByServletStatus(Integer servletStatus)
return HttpStatus.valueOf(servletStatus);
并将您的代码更改为:
if (servletStatus != null && servletStatus instanceof Integer)
status = getHttpStatusByServletStatus(servletStatus);
然后是测试类:
公共 ApiErrorControllerTest
@Spy
private ApiErrorController apiErrorController;
@Mock
HttpServletRequest requestMock;
@Mock
HttpServletResponse responseMock;
@Befire
public void init()
MockitoAnnotations.initMocks(this);
@Test
public void test()
// Arrange
HttpStatus expectedStatus = // expected status
String expectedErrorMessage = // ..
doReturn(expectedStatus).when(apiErrorController)
.getHttpStatusByServletStatus(Mockito.anyString());
when(requestMock.getAttribute("javax.servlet.error.message"))
.thenReturn(expectedErrorMessage);
// other setup..
// Act
apiErrorController.error(requestMock, responseMock);
// Assertions
【讨论】:
谢谢。但我不想只测试error
方法的逻辑。我想使用我提到的AbcController
进行测试。我想要的是当AbcController
中发生错误时,那么ApiErrorController
中的error
方法可以成功处理。
那么基本上你想写一个集成测试?
是的,你可以这么想。也许它看起来像一个集成测试。
好吧,如果没有这里的 impl,我不能说任何话......你不能重现那个场景的问题是什么?以上是关于如何使用junit在spring-boot中测试常见错误ErrorController的主要内容,如果未能解决你的问题,请参考以下文章
如何在spring-boot应用程序的junit中调用ApplicationContextInitializer
Spring-boot,使用不同配置文件的 JUnit 测试