@ControllerAdvice 单元测试控制器中的自动装配 MessageSource null

Autowired MessageSource null in @ControllerAdvice unit testing controller

我已经将 setHandlerExceptionResovlers 添加到我的构建器中并且效果很好,除了异常处理程序 bean 具有自动装配的 MessageSource 并且在单元测试时这是空的。我认为这可能是必须在测试中手动设置异常处理程序的原因。流程使用无效参数调用控制器,控制器使用 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);
            }   

我不得不在我的测试配置中手动注册 MessageSource,并在 ControllerAdvice 中创建一个构造函数来添加参数 MeasageSource。我的 JSON 响应未找到 MessageConverter 也有问题,必须在 ExceptionHandlerExceptionResolver 中设置转换。编辑我的问题以显示反映的更改。