2015-02-04 6 views
7

में खाली अपवाद निकाय मुझे प्रतिक्रिया बॉडी में अपवाद संदेश शामिल करने के लिए MockMvc बनाने की कोशिश करते समय परेशानी हो रही है।स्प्रिंग एमवीसी टेस्ट

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

जहां BadRequestException इस तरह sth दिखता है:: मैं एक नियंत्रक के रूप में निम्नानुसार है

@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) { /* ... */ } 

} 

और मैं /user/new नियंत्रक के खिलाफ निम्न परीक्षण चलाने: जो निम्नलिखित उत्पादन प्रिंट

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

:

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 = [] 

क्या किसी को पता है कि Bodyprint() आउटपुट में क्यों गुम है?

संपादित करें: मैं किसी भी कस्टम अपवाद हैंडलर का उपयोग नहीं कर रहा हूं और जब मैं सर्वर चलाता हूं तो कोड अपेक्षित काम करता है। यही है, एप्लिकेशन को चलाने और सर्वर को एक ही अनुरोध करने से

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

अपेक्षित के रूप में वापस लौटाता है। इसलिए, मुझे लगता है कि MockMvc के साथ एक समस्या है। यह किसी भी तरह अपवाद के message फ़ील्ड को कैप्चर करने से चूकता है, जबकि नियमित अनुप्रयोग सर्वर का डिफ़ॉल्ट अपवाद हैंडलर अपेक्षा के अनुसार काम करता है।

उत्तर

5

इस मुद्दे के लिए ticket खोलने के बाद, मुझे बताया गया कि शरीर में त्रुटि संदेश को स्प्रिंग बूट द्वारा ख्याल रखा जाता है जो सर्वलेट कंटेनर स्तर पर त्रुटि मैपिंग कॉन्फ़िगर करता है और चूंकि स्प्रिंग एमवीसी टेस्ट रन के साथ हूं ओक सर्वलेट अनुरोध/प्रतिक्रिया, ऐसी कोई त्रुटि मैपिंग नहीं है। इसके अलावा, उन्होंने मुझे कम से कम एक @WebIntegrationTest बनाने और मेरे नियंत्रक तर्क के लिए स्प्रिंग एमवीसी टेस्ट से चिपकने की सलाह दी।

आखिरकार, मैंने अपने स्वयं के कस्टम अपवाद हैंडलर के साथ जाने का फैसला किया और बाकी के लिए MockMvc पर चिपक गया।

@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

यह संभावना है कि आपने या तो अपवाद को संभाला नहीं है या आपने वास्तव में शरीर को खाली छोड़ दिया है। अपवाद को संभालने या तो नियंत्रक

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

या उपयोगकर्ता वैश्विक त्रुटि हैंडलर अगर आप 3.2 पर या

@ControllerAdvice 
public class GlobalExceptionHandler { 

    @ExceptionHandler 
    public @ResponseBody String handleBadRequestException(BadRequestException ex) { 
     return "I'm the body"; 
    } 
} 
इस के साथ

से ऊपर हैं शरीर को पॉप्युलेट हो जाएगा में एक त्रुटि हैंडलर जोड़ने के लिए, आपको इसे अपने त्रुटि संदेश के साथ पॉप्युलेट करें

+1

मैं डिफ़ॉल्ट अपवाद हैंडलर का उपयोग कर रहा हूं। समस्या यह है कि, 'MockMvc'' संदेश' फ़ील्ड को कैप्चर नहीं करता है, जबकि नियमित अनुप्रयोग सर्वर का डिफ़ॉल्ट अपवाद हैंडलर करता है। (प्रश्न में मेरा संपादन देखें।) –

संबंधित मुद्दे