I have added the setHandlerExceptionResovlers to my builder and that works well except the exceptionhandler bean has autowired MessageSource and when unit testing this is null. I assume it might be cause of having to manually setup the exception handler in test. The flow is calling the controller with invalid parm, the controller calls the exception handler with a BindException.
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = AutoControllerTest.TestContextConfiguration.class)
@WebAppConfiguration
public class AutoControllerTest {
@Mock
private AutoFacade policyFacade;
@Mock
private MessageSource messageSource;
@Mock
private RestExceptionProcessor processor;
@InjectMocks
private AutoController policyController;
private MockMvc mockMvc;
String validPolicyNbr;
String tooLongPolicyNbr;
AutoPolicy autoPolicy;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(policyController)
.setHandlerExceptionResolvers(createExceptionResolver())
.build();
tooLongPolicyNbr = new String("000000000000000000000000");
validPolicyNbr = new String("4239326");
autoPolicy = new AutoPolicy();
}
private ExceptionHandlerExceptionResolver createExceptionResolver() {
ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() {
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(HandlerMethod handlerMethod, Exception exception) {
Method method = new ExceptionHandlerMethodResolver(RestExceptionProcessor.class).resolveMethod(exception);
// Changed return new ServletInvocableHandlerMethod(new
//RestExceptionProcessor(), method);
//Changed to resolve question
return new ServletInvocableHandlerMethod(new RestExceptionProcessor(messageSource), method);
}
};
//Added to resolve question
exceptionResolver.getMessageConverters().add(
new MappingJackson2HttpMessageConverter());
//Finish
exceptionResolver.afterPropertiesSet();
return exceptionResolver;
}
@Test
public void getPolicyDetails_TooLongPolicyNbr_ReturnsDetails() throws Exception {
/** Removed **/
// MessageSource ms = messageSource;
// processor.setMessageSource(ms);
this.mockMvc.perform(get("/policies/policy/{policyNbr}", tooLongPolicyNbr))
.andDo(print())
.andExpect(status().isOk());
}
@EnableAutoConfiguration
@ComponentScan(basePackages = { "com.api" })
@Configuration
static public class TestContextConfiguration {
//Removed
//@Bean
//public MessageSource messageSource() {
//return Mockito.mock(MessageSource.class);
//}
//Removed End
//Added
@Bean
public MessageSource messageSource() {
final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames( "classpath:messages" );
messageSource.setDefaultEncoding( "UTF-8" );
messageSource.setCacheSeconds( 60 );
messageSource.setFallbackToSystemLocale( false );
return messageSource;
}
//Added end
@Bean
public AutoFacade policyFacade() {
return Mockito.mock(AutoFacade.class);
}
@Bean
public HttpServletRequest request() {
return Mockito.mock(HttpServletRequest.class);
}
@Bean
public RestExceptionProcessor processor() {
return Mockito.mock(RestExceptionProcessor.class);
}
}
}
@ControllerAdvice
public class RestExceptionProcessor {
private static final Logger logger = LoggerFactory.getLogger(RestExceptionProcessor.class);
@Autowired
private MessageSource messageSource;
//Removed
//public void setMessageSource(MessageSource ms){
// this.messageSource = ms;
// }
//Added
public RestExceptionProcessor(MessageSource messageSource) {
super();
this.messageSource = messageSource;
}
public RestExceptionProcessor() {
super();
}
@ExceptionHandler({BindException.class})
@ResponseStatus(value=HttpStatus.BAD_REQUEST)
@ResponseBody
public APIStatus validationError(BindException ex) {
int statusCd = Integer.parseInt(HttpStatus.BAD_REQUEST.toString());
String statusMessage = messageSource.getMessage("bad.request.status.msg.400", null, Locale.US);
String errorURL = null;
int errorCode = 400000;
String errorType = messageSource.getMessage("bad.request.error.type.400", null, Locale.US);
List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
List<com.fbitn.api.errors.FieldError> apiFieldErrors = new ArrayList<com.fbitn.api.errors.FieldError>();
for (FieldError fieldError: fieldErrors) {
String errorMessage = messageSource.getMessage(fieldError, Locale.US);
com.fbitn.api.errors.FieldError apiFieldError = new com.fbitn.api.errors.FieldError(fieldError.getField(), errorMessage);
apiFieldErrors.add(apiFieldError);
}
APIError apiError = new APIError(errorCode, errorType, "Validation Error", apiFieldErrors);
List<APIError> errorInfoList = new ArrayList<APIError>();
errorInfoList.add(apiError);
return new APIStatus(statusCd, errorURL, statusMessage, errorInfoList);
}
I had to manually register the MessageSource in my test configs and create a constructor in the ControllerAdvice to add parm MeasageSource. Also had an issue with MessageConverter not being found for my JSON response, had to set the convert in ExceptionHandlerExceptionResolver. Edited my question to show the reflected changes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With