2014-07-15 5 views
4

제 문제는 @ExceptionHandler와 함께 @ControllerAdvice를 사용하는 Spring @RestController 테스트와 관련이 있습니다. 여기 코드는 다음과 같습니다@ControllerAdvice를 사용하여 @RestController를 테스트하십시오.

@ControllerAdvice 클래스 :

@ControllerAdvice 
public class MyAppExceptionHandler { 

    @ExceptionHandler({ NoSuchEntityException.class }) 
    @ResponseStatus(value = HttpStatus.NOT_FOUND) 
    public @ResponseBody 
    ErrorDTO handleNotFoundException(Exception ex) throws IOException { 

     return new ErrorDTO.Builder().setStatus(HttpStatus.NOT_FOUND) 
       .setCause(ex.getClass().getName()) 
       .setThrowable(ex).build(); 
    } 
} 

애플리케이션 모두에서 사용 잘 작동 - 완벽 JSON의 설명과 함께 404 응답을 받고 있지만, 때 시험 중에 그것을 사용하려고 - 나쁜 일이 일어날.

내 테스트 클래스 :

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = { WebConfig.class }) 
@WebAppConfiguration 
public class SomeTest { 

    @Mock 
    private SomeService service; 

    @InjectMocks 
    private SomeController controller; 

    private MockMvc mvc; 

    private ExceptionHandlerExceptionResolver createExceptionResolver() { 
     ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() { 
      @Override 
      protected ServletInvocableHandlerMethod getExceptionHandlerMethod(
       HandlerMethod handlerMethod, Exception exception) { 
       Method method = new ExceptionHandlerMethodResolver(
         MyAppExceptionHandler.class).resolveMethod(exception); 
       return new ServletInvocableHandlerMethod(
        new MyAppExceptionHandler(), method); 
      } 
     }; 
     exceptionResolver.afterPropertiesSet(); 
     return exceptionResolver; 
    } 

    @Before 
    public void setup() { 

     MockitoAnnotations.initMocks(this); 
     mvc = MockMvcBuilders.standaloneSetup(controller) 
       .setHandlerExceptionResolvers(createExceptionResolver()) 
       .build(); 
    } 

    @Test 
    public void thatExceptionHappens() throws Exception { 

     when(service.get(10)).thenThrow(new NoSuchEntityException(Some.class, 10)); 

     mvc.perform(get("/api/some/10")).andExpect(status().isNotFound()); 
    } 
} 

을 실행하려고 :

2014-07-15 19:35:01.376 [main] ERROR com.package.SomeTest$1 - Failed to invoke @ExceptionHandler method: public com.package.ErrorDTO com.package.MyAppExceptionHandler.handleNotFoundException(java.lang.Exception) throws java.io.IOException 
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation 

은 아마 MappingJackson2HttpMessageConverter 테스트 광산 @ExceptionHandler 동안로드되지 않는다는 생각은 (그러나 그것은 WebConfig에서 구성됩니다. 어떤 예외도 던지지 않는 전형적인 테스트를 수행하려고 할 때 - 모든 것이 잘 동작합니다.

미리 도움을 주셔서 감사합니다.

+0

WebConfig의 내용은 무엇입니까? – denisazevedo

+0

질문을하고 사람들은 대답 할 시간을 가졌습니다. 답변을 수락하십시오. –

답변

13

I는이에 대한 최선의 해결책 (나는 다른 하나를 듣고 싶습니다),
가 있는지 확실하지 않습니다하지만 내가이 정확하게 당신이 직면하고 발급 해결 방법입니다

이 추가 당신의 createExceptionResolver()에 라인이 같은

exceptionResolver.getMessageConverters().add(
     new MappingJackson2HttpMessageConverter()); 

뭔가 :

private ExceptionHandlerExceptionResolver createExceptionResolver() { 
    ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() { 
     @Override 
     protected ServletInvocableHandlerMethod getExceptionHandlerMethod(
      HandlerMethod handlerMethod, Exception exception) { 
      Method method = new ExceptionHandlerMethodResolver(
        MyAppExceptionHandler.class).resolveMethod(exception); 
      return new ServletInvocableHandlerMethod(
       new MyAppExceptionHandler(), method); 
     } 
    }; 
    exceptionResolver.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); 
    exceptionResolver.afterPropertiesSet(); 
    return exceptionResolver; 
} 

내가 모르는 어떤 이유로 들어, 봄이 아니었다 로드 중 내 MappingJackson2HttpMessageConverter.
그 행이 내 문제를 해결했습니다.

+3

빌더에서'HandlerExceptionResolvers'를 설정하면 모든 기본 설정을 지우고 대신 자신의 설정을 사용하게됩니다. 예를 들어 유효성 검사 주석을 사용하는 테스트가 있고 Spring의 적절한 응답을 예상하는 경우 문제가 발생할 수 있습니다. 저는 Spring에서 우리가 겹쳐 쓰는 대신 해결자를 _add_ 할 수 있도록 요청합니다 : https://jira.spring.io/browse/SPR-12751 –

3

MockMvcBuilders standaloneSetup은 정의 상 수동으로 Spring 구성에서 @ControllerAdvice와 같은 관심있는 Spring Bean을 발견하지 않고 테스트에 필요한 것을 수동으로 설정할 수 있음을 의미합니다. 대신 standaloneSetup을 사용하면 @ControllerAdvice Bean을 수동으로 등록 할 수 있습니다. 그 일을 만들기위한 티켓이 있습니다. https://jira.spring.io/browse/SPR-12751을 참조하십시오.

+0

@Rossen에게 이것을 구현해 주셔서 감사합니다. Spring 4.2에는이 개선이 포함되어 있으며 * Spring Boot * 1.3.0에는 Spring 4.2 이상에 대한 종속성이 있으므로이 기능도 제공됩니다. –

관련 문제