我正在测试我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
带有消息的 insted 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 讨论之后,我尝试这样做,我只是添加了一个带有所需bean 的内部@Configuration 类:
@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 之前测试在没有配置的情况下工作?