2017-03-13 47 views
1

在spring引導項目中,我想用Junit測試我的ErrorController。 代碼如下代碼片段所示。如何在Junit的spring-boot中測試常見錯誤ErrorController

@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; 
    } 
} 

當我的控制器(例如AbcController)發生業務異常時,程序進入ExceptionControllerAdvice類。 如果在ExceptionControllerAdvice中發生異常,那麼程序將進入上述ApiErrorController類。

有人能告訴我如何測試HttpStatus.valueOf(servletStatus)失敗的情況嗎? 另外,我想request.getAttribute("javax.servlet.error.message")返回一個非空字符串。 如何實現我想測試的內容?

順便說一句,我不想只測試error方法的邏輯。我想用我提到的AbcController進行測試。我想要的是當AbcController中發生錯誤時,ApiErrorController中的error方法可以成功處理它。

APPEND: 例如,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來處理這個錯誤。

程序如何生成特定的servletStatusjavax.servlet.error.message?如何模擬做到這一點?

回答

0

首先在這種錯誤方法中有很多事情要做。你可能會考慮將某些邏輯轉移到專門的類/公共方法。

除此之外,我會建議使用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 
} 
+0

T要你。但我不想只測試'error'方法的邏輯。我想用我提到的'AbcController'來做測試。我想要的是當'AbcController'中發生錯誤時,那麼'ApiErrorController'中的'error'方法可以成功處理它。 – niaomingjian

+0

所以基本上你想寫一個集成測試? –

+0

是的,你可以這樣想。也許它看起來像一個集成測試。 – niaomingjian