2015-02-04 21 views
7

Tôi gặp sự cố khi cố gắng tạo MockMvc để bao gồm thông báo ngoại lệ trong nội dung phản hồi. Tôi có một bộ điều khiển như sau:Nội dung ngoại lệ trống trong Spring MVC Test

@RequestMapping("/user/new") 
public AbstractResponse create(@Valid NewUserParameters params, BindingResult bindingResult) { 
    if (bindingResult.hasErrors()) throw BadRequestException.of(bindingResult); 
    // ... 
} 

nơi BadRequestException trông sth như thế này:

@ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "bad request") 
public class BadRequestException extends IllegalArgumentException { 

    public BadRequestException(String cause) { super(cause); } 

    public static BadRequestException of(BindingResult bindingResult) { /* ... */ } 

} 

Và tôi chạy thử nghiệm sau đây đối với /user/new điều khiển:

@Test 
public void testUserNew() throws Exception { 
    getMockMvc().perform(post("/user/new") 
      .param("username", username) 
      .param("password", password)) 
      .andDo(print()) 
      .andExpect(status().isOk()); 
} 

đó in ra sau đây :

Resolved Exception: 
       Type = controller.exception.BadRequestException 

     ModelAndView: 
      View name = null 
       View = null 
       Model = null 

      FlashMap: 

MockHttpServletResponse: 
       Status = 400 
     Error message = bad request 
      Headers = {X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Frame-Options=[DENY]} 
     Content type = null 
       Body = 
     Forwarded URL = null 
     Redirected URL = null 
      Cookies = [] 

Có ai có ý tưởng về lý do tại sao Body bị thiếu trong đầu ra print() không?

Chỉnh sửa: Tôi không sử dụng bất kỳ trình xử lý ngoại lệ tùy chỉnh nào và mã hoạt động như mong đợi khi tôi chạy máy chủ. Tức là, chạy ứng dụng và thực hiện cùng một yêu cầu đến máy chủ trả lại

{"timestamp":1423076185822, 
"status":400, 
"error":"Bad Request", 
"exception":"controller.exception.BadRequestException", 
"message":"binding failed for field(s): password, username, username", 
"path":"/user/new"} 

như mong đợi. Do đó, có một vấn đề với MockMvc tôi giả sử. Nó bằng cách nào đó bỏ lỡ để nắm bắt trường message của ngoại lệ, trong khi trình xử lý ngoại lệ mặc định của máy chủ ứng dụng thông thường hoạt động như mong đợi.

Trả lời

5

Sau khi mở ticket cho vấn đề này, tôi được thông báo rằng thông báo lỗi trong cơ thể được Spring Boot cấu hình ánh xạ lỗi ở cấp vùng chứa Servlet và kể từ khi chạy thử MVC Spring với AM ock Yêu cầu/phản hồi của Servlet, không có ánh xạ lỗi như vậy. Hơn nữa, họ khuyên tôi nên tạo ít nhất một @WebIntegrationTest và dính vào Kiểm tra MVC mùa xuân cho logic điều khiển của tôi.

Cuối cùng, tôi quyết định đi với trình xử lý ngoại lệ tùy chỉnh của riêng mình và dính vào MockMvc cho phần còn lại như trước đây.

@ControllerAdvice 
public class CustomExceptionHandler { 

    @ExceptionHandler(Throwable.class) 
    public @ResponseBody 
    ExceptionResponse handle(HttpServletResponse response, Throwable throwable) { 
     HttpStatus status = Optional 
       .ofNullable(AnnotationUtils.getAnnotation(throwable.getClass(), ResponseStatus.class)) 
       .map(ResponseStatus::value) 
       .orElse(HttpStatus.INTERNAL_SERVER_ERROR); 
     response.setStatus(status.value()); 
     return new ExceptionResponse(throwable.getMessage()); 
    } 

} 

@Data 
public class ExceptionResponse extends AbstractResponse { 

    private final long timestamp = System.currentTimeMillis(); 

    private final String message; 

    @JsonCreator 
    public ExceptionResponse(String message) { 
     checkNotNull(message, "message == NULL"); 
     this.message = message; 
    } 

} 
3

Điều này có thể có nghĩa là bạn đã không xử lý ngoại lệ hoặc bạn thực sự đã để trống phần thân. Để xử lý các ngoại lệ hoặc thêm một xử lý lỗi trong bộ điều khiển

@ExceptionHandler 
public @ResponseBody String handle(BadRequestException e) { 
    return "I'm the body"; 
} 

ngừơi tiêu dùng của các lỗi xử lý toàn cầu nếu bạn đang ở trên 3.2 hoặc cao hơn

@ControllerAdvice 
public class GlobalExceptionHandler { 

    @ExceptionHandler 
    public @ResponseBody String handleBadRequestException(BadRequestException ex) { 
     return "I'm the body"; 
    } 
} 

với điều này cơ thể sẽ được cư, bạn nên điền vào nó với thông báo lỗi của bạn

+1

Tôi đang sử dụng trình xử lý ngoại lệ mặc định. Vấn đề là, 'MockMvc' không nắm bắt trường' message', trong khi trình xử lý ngoại lệ mặc định của máy chủ ứng dụng thông thường. (Xem chỉnh sửa của tôi cho câu hỏi.) –

Các vấn đề liên quan