스프링 MockMv의 단독 모드를 사용해서 한 개 컨트롤러에 대한 MockMvc를 생성하고, 테스트 코드를 작성했다.
mockMvc = MockMvcBuilders.standaloneSetup(SomeController).build();
여기서 문제는 익셉션 상황을 테스트하는 코드에서 발생했다. 이 프로젝트에서는 컨트롤러에서 발생한 익셉션의 처리를 표준화하기 위해 @ControllerAdvice를 사용했는데, 위와 같이 컨트롤러 단독 모드로 생성한 MockMvc의 경우 @ControllerAdvice를 이용한 익셉션 처리가 되지 않는 것이었다.
다행히 단독 모드로 생성한 StandaloneMockMvcBuilder는 다음의 메서드를 제공하고 있었다.
setHandlerExceptionResolvers(HandlerExceptionResolver... exceptionResolvers)
그래서, @ControllerAdvice를 지정한 클래스를 익셉션 핸들러로 사용하는 ExceptionHandlerExceptionResolver의 구현 객체를 만들어서 사용하기로 했다. 그 구현 객체를 생성하는 코드는 다음과 같다.
public static ExceptionHandlerExceptionResolver createExceptionResolver() {
ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() {
@Override
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(
HandlerMethod handlerMethod, Exception exception) {
// 익셉션을 CommonExceptionHandler가 처리하도록 설정
Method method = new ExceptionHandlerMethodResolver(
CommonExceptionHandler.class).resolveMethod(exception);
return new ServletInvocableHandlerMethod(new CommonExceptionHandler(), method);
}
};
exceptionResolver.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
exceptionResolver.afterPropertiesSet();
return exceptionResolver;
}
위 코드에서 눈여겨 볼 점은 생성한 exceptionResolver에 알맞은 MessageConverter를 등록했다는 점이다. 새로 등록한 ExceptionResolver는 독립 모드로 생성한 MokcMvc가 사용하는 MessageConverter를 사용하지 않기 때문에, 위 코드처럼 필요한 MessageConverter를 ExceptionResolver에 직접 등록해 주었다.
@ControllerAdvice 클래스를 이용해서 익셉션을 처리하는 ExceptionResolver를 생성하는 기능을 만들었으니 이제 이 기능을 사용해서 MockMvc를 생성하면 된다.
mockMvc = MockMvcBuilders.standaloneSetup(someController)
.setHandlerExceptionResolvers(createExceptionResolver()).build();
이제 someController에서 익셉션이 발생하면, @ControllerAdvice를 적용한 클래스를 이용해서 익셉션을 처리할 수 있게 된다.