Regression tests for @RestControllerAdvice support in MockMvc
This commit introduces regression tests for @RestControllerAdvice support in standalone MockMvc configurations. See gh-25520
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -18,11 +18,16 @@ package org.springframework.test.web.servlet.samples.standalone;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||||
@@ -32,19 +37,20 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
|
|||||||
* Exception handling via {@code @ExceptionHandler} method.
|
* Exception handling via {@code @ExceptionHandler} method.
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
* @author Sam Brannen
|
||||||
*/
|
*/
|
||||||
public class ExceptionHandlerTests {
|
public class ExceptionHandlerTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExceptionHandlerMethod() throws Exception {
|
public void mvcLocalExceptionHandlerMethod() throws Exception {
|
||||||
standaloneSetup(new PersonController()).build()
|
standaloneSetup(new PersonController()).build()
|
||||||
.perform(get("/person/Clyde"))
|
.perform(get("/person/Clyde"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(forwardedUrl("errorView"));
|
.andExpect(forwardedUrl("errorView"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGlobalExceptionHandlerMethod() throws Exception {
|
public void mvcGlobalExceptionHandlerMethod() throws Exception {
|
||||||
standaloneSetup(new PersonController()).setControllerAdvice(new GlobalExceptionHandler()).build()
|
standaloneSetup(new PersonController()).setControllerAdvice(new GlobalExceptionHandler()).build()
|
||||||
.perform(get("/person/Bonnie"))
|
.perform(get("/person/Bonnie"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
@@ -52,13 +58,60 @@ public class ExceptionHandlerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGlobalExceptionHandlerMethodUsingClassArgument() throws Exception {
|
public void mvcGlobalExceptionHandlerMethodUsingClassArgument() throws Exception {
|
||||||
standaloneSetup(PersonController.class).setControllerAdvice(GlobalExceptionHandler.class).build()
|
standaloneSetup(PersonController.class).setControllerAdvice(GlobalExceptionHandler.class).build()
|
||||||
.perform(get("/person/Bonnie"))
|
.perform(get("/person/Bonnie"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andExpect(forwardedUrl("globalErrorView"));
|
.andExpect(forwardedUrl("globalErrorView"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void restNoException() throws Exception {
|
||||||
|
standaloneSetup(RestPersonController.class)
|
||||||
|
.setControllerAdvice(RestGlobalExceptionHandler.class, RestPersonControllerExceptionHandler.class).build()
|
||||||
|
.perform(get("/person/Yoda").accept(MediaType.APPLICATION_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.name").value("Yoda"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void restLocalExceptionHandlerMethod() throws Exception {
|
||||||
|
standaloneSetup(RestPersonController.class)
|
||||||
|
.setControllerAdvice(RestGlobalExceptionHandler.class, RestPersonControllerExceptionHandler.class).build()
|
||||||
|
.perform(get("/person/Luke").accept(MediaType.APPLICATION_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.error").value("local - IllegalArgumentException"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void restGlobalExceptionHandlerMethod() throws Exception {
|
||||||
|
standaloneSetup(RestPersonController.class)
|
||||||
|
.setControllerAdvice(RestGlobalExceptionHandler.class).build()
|
||||||
|
.perform(get("/person/Leia").accept(MediaType.APPLICATION_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.error").value("global - IllegalStateException"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void restGlobalRestPersonControllerExceptionHandlerTakesPrecedenceOverGlobalExceptionHandler() throws Exception {
|
||||||
|
standaloneSetup(RestPersonController.class)
|
||||||
|
.setControllerAdvice(RestGlobalExceptionHandler.class, RestPersonControllerExceptionHandler.class).build()
|
||||||
|
.perform(get("/person/Leia").accept(MediaType.APPLICATION_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.error").value("globalPersonController - IllegalStateException"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // gh-25520
|
||||||
|
public void restNoHandlerFound() throws Exception {
|
||||||
|
standaloneSetup(RestPersonController.class)
|
||||||
|
.setControllerAdvice(RestGlobalExceptionHandler.class, RestPersonControllerExceptionHandler.class)
|
||||||
|
.addDispatcherServletCustomizer(dispatcherServlet -> dispatcherServlet.setThrowExceptionIfNoHandlerFound(true))
|
||||||
|
.build()
|
||||||
|
.perform(get("/bogus").accept(MediaType.APPLICATION_JSON))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.error").value("global - NoHandlerFoundException"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
private static class PersonController {
|
private static class PersonController {
|
||||||
@@ -80,7 +133,6 @@ public class ExceptionHandlerTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ControllerAdvice
|
@ControllerAdvice
|
||||||
private static class GlobalExceptionHandler {
|
private static class GlobalExceptionHandler {
|
||||||
|
|
||||||
@@ -88,7 +140,73 @@ public class ExceptionHandlerTests {
|
|||||||
public String handleException(IllegalStateException exception) {
|
public String handleException(IllegalStateException exception) {
|
||||||
return "globalErrorView";
|
return "globalErrorView";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
private static class RestPersonController {
|
||||||
|
|
||||||
|
@GetMapping("/person/{name}")
|
||||||
|
Person get(@PathVariable String name) {
|
||||||
|
switch (name) {
|
||||||
|
case "Luke":
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
case "Leia":
|
||||||
|
throw new IllegalStateException();
|
||||||
|
default:
|
||||||
|
return new Person("Yoda");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler
|
||||||
|
Error handleException(IllegalArgumentException exception) {
|
||||||
|
return new Error("local - " + exception.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestControllerAdvice(assignableTypes = RestPersonController.class)
|
||||||
|
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||||
|
private static class RestPersonControllerExceptionHandler {
|
||||||
|
|
||||||
|
@ExceptionHandler
|
||||||
|
Error handleException(Throwable exception) {
|
||||||
|
return new Error("globalPersonController - " + exception.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestControllerAdvice
|
||||||
|
@Order(Ordered.LOWEST_PRECEDENCE)
|
||||||
|
private static class RestGlobalExceptionHandler {
|
||||||
|
|
||||||
|
@ExceptionHandler
|
||||||
|
Error handleException(Throwable exception) {
|
||||||
|
return new Error( "global - " + exception.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Person {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
Person(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Error {
|
||||||
|
|
||||||
|
private final String error;
|
||||||
|
|
||||||
|
Error(String error) {
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getError() {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user