MockMvc和@ControllerAdvice在测试中不起作用

时间:2019-08-28 08:11:08

标签: java spring-boot mockmvc controller-advice

我正在用RestController测试mockMvc。我有一个全局RestExceptionHandler来解决所有异常。在我的RestController中,我像这样抛出了自定义Exception RequestValidationException

    @ApiOperation("Search something")
    @RequestMapping(path = "/search", method = RequestMethod.POST)
    public CompletableFuture<SomeResponse> search(
            @RequestBody @Validated SearchRequest request, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            throw new RequestValidationException(bindingResult);
        }
        return searchService.search(request);
    }

当我传递空请求时,它必须抛出RequestValidationException(bindingResult)

但是当我开始测试时,它们落在我抛出Exception的地方,而不是解决它。

我尝试这样配置mockMvc

@RunWith(SpringRunner.class)
public class SearchControllerTest {
    private MockMvc mockMvc;

    @InjectMocks
    protected SearchController searchController;

    @MockBean
    private SearchService searchService;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        this.mockMvc = MockMvcBuilders.standaloneSetup(searchController)
                .setHandlerExceptionResolvers(getHandlerExceptionResolver())
                .build();
    }

  private HandlerExceptionResolver getHandlerExceptionResolver() {
        final StaticApplicationContext applicationContext = new StaticApplicationContext();
        applicationContext.registerSingleton("exceptionHandler", RestExceptionHandler.class);

        final WebMvcConfigurationSupport webMvcConfigurationSupport = new WebMvcConfigurationSupport();
        webMvcConfigurationSupport.setApplicationContext(applicationContext);
        return webMvcConfigurationSupport.handlerExceptionResolver();
    }

但是没有帮助。我收到带有消息的Exception插入的json。

我的RequestValidationExceptionHandler

@Component
public class RequestValidationExceptionHandler implements ApiExceptionHandler {

    @Override
    public ResponseEntity<ApiResponse> process(Throwable throwable) {
        RequestValidationException e = (RequestValidationException) throwable;

        if (e.getBindingResult() != null) {
            return new ResponseEntity<>(ApiResponse.badRequest(e.getBindingResult()), HttpStatus.OK);
        }

        return new ResponseEntity<>(ApiResponse.badRequest(throwable, ApiResponseCode.BAD_REQUEST), HttpStatus.OK);
    }

    @Override
    public Class<? extends Throwable> getSupportedException() {
        return RequestValidationException.class;
    }
}

2)我的@ControllerAdvice

@Slf4j
@ControllerAdvice
@SuppressWarnings({"checkstyle:JavadocMethod", "checkstyle:MultipleStringLiterals"})
public class RestExceptionHandler {

    @Autowired
    private ExceptionHandlerRegistry handlerRegistry;

    @ExceptionHandler
    public ResponseEntity handleThrowable(Throwable throwable, WebRequest request) {
        request.setAttribute(Constants.ERROR_ATTRIBUTE_NAME, throwable, RequestAttributes.SCOPE_REQUEST);

        Throwable ex = throwable instanceof CompletionException ?
                ObjectUtils.defaultIfNull(throwable.getCause(), throwable) : throwable;

        for (ApiExceptionHandler handler : handlerRegistry.getHandlers()) {
            if (handler.isSupported(ex)) {
                return handler.process(ex);
            }
        }

        return new ResponseEntity<>(ApiResponse.badRequest(throwable, ApiResponseCode.SERVER_ERROR), HttpStatus.OK);
    }
}

3)和ExceptionHandlerRegistry

@Component
public class ExceptionHandlerRegistry {

    @Getter
    private final List<ApiExceptionHandler> handlers;

    @Autowired
    public ExceptionHandlerRegistry(List<ApiExceptionHandler> handlers) {
        this.handlers = ObjectUtils.defaultIfNull(handlers, Collections.emptyList());
    }
}

错误消息: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is ru.filit.mvideo.mb2c.api.exceptions.RequestValidationException

更新 因此,在与@MichaelMichailidis进行了一些讨论之后,我尝试执行此操作,我只添加了一个内部@Configuration类以及所需的bean:


    @TestConfiguration
    static class SearchControllerTestConfiguration {

        @Bean
        public RequestValidationExceptionHandler requestValidationExceptionHandler(){
            return new RequestValidationExceptionHandler();
        }

        @Bean
        public ExceptionHandlerRegistry getExceptionHandlerRegistry(final RequestValidationExceptionHandler requestValidationExceptionHandler){
            return new ExceptionHandlerRegistry(Collections.singletonList(requestValidationExceptionHandler));
        }

        @Bean
        public RestExceptionHandler getRestExceptionHandler(){
            return new RestExceptionHandler();
        }
    }

和我的测试合格。但是我不明白为什么在添加@ControllerAdvice之前没有配置就可以进行测试?

1 个答案:

答案 0 :(得分:0)

您可以尝试在测试类中导入异常处理程序:

@RunWith(SpringRunner.class)
@Import(RestExceptionHandler.class)  // EXCEPTION HANDLER CLASS
public class SearchControllerTest {