1
1
/*
2
- * Copyright 2002-2018 the original author or authors.
2
+ * Copyright 2002-2020 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
18
18
19
19
import org .junit .Test ;
20
20
21
+ import org .springframework .core .Ordered ;
22
+ import org .springframework .core .annotation .Order ;
23
+ import org .springframework .http .MediaType ;
21
24
import org .springframework .stereotype .Controller ;
22
25
import org .springframework .web .bind .annotation .ControllerAdvice ;
23
26
import org .springframework .web .bind .annotation .ExceptionHandler ;
27
+ import org .springframework .web .bind .annotation .GetMapping ;
24
28
import org .springframework .web .bind .annotation .PathVariable ;
25
- import org .springframework .web .bind .annotation .RequestMapping ;
26
- import org .springframework .web .bind .annotation .RequestMethod ;
29
+ import org .springframework .web .bind .annotation .RestController ;
30
+ import org .springframework .web .bind .annotation .RestControllerAdvice ;
27
31
28
32
import static org .springframework .test .web .servlet .request .MockMvcRequestBuilders .*;
29
33
import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .*;
33
37
* Exception handling via {@code @ExceptionHandler} method.
34
38
*
35
39
* @author Rossen Stoyanchev
40
+ * @author Sam Brannen
36
41
*/
37
42
public class ExceptionHandlerTests {
38
43
39
44
@ Test
40
- public void testExceptionHandlerMethod () throws Exception {
45
+ public void mvcLocalExceptionHandlerMethod () throws Exception {
41
46
standaloneSetup (new PersonController ()).build ()
42
- .perform (get ("/person/Clyde" ))
47
+ .perform (get ("/person/Clyde" ))
43
48
.andExpect (status ().isOk ())
44
49
.andExpect (forwardedUrl ("errorView" ));
45
50
}
46
51
47
52
@ Test
48
- public void testGlobalExceptionHandlerMethod () throws Exception {
53
+ public void mvcGlobalExceptionHandlerMethod () throws Exception {
49
54
standaloneSetup (new PersonController ()).setControllerAdvice (new GlobalExceptionHandler ()).build ()
50
55
.perform (get ("/person/Bonnie" ))
51
56
.andExpect (status ().isOk ())
52
57
.andExpect (forwardedUrl ("globalErrorView" ));
53
58
}
54
59
60
+ @ Test
61
+ public void restNoException () throws Exception {
62
+ standaloneSetup (new RestPersonController ())
63
+ .setControllerAdvice (new RestGlobalExceptionHandler (), new RestPersonControllerExceptionHandler ()).build ()
64
+ .perform (get ("/person/Yoda" ).accept (MediaType .APPLICATION_JSON ))
65
+ .andExpect (status ().isOk ())
66
+ .andExpect (jsonPath ("$.name" ).value ("Yoda" ));
67
+ }
68
+
69
+ @ Test
70
+ public void restLocalExceptionHandlerMethod () throws Exception {
71
+ standaloneSetup (new RestPersonController ())
72
+ .setControllerAdvice (new RestGlobalExceptionHandler (), new RestPersonControllerExceptionHandler ()).build ()
73
+ .perform (get ("/person/Luke" ).accept (MediaType .APPLICATION_JSON ))
74
+ .andExpect (status ().isOk ())
75
+ .andExpect (jsonPath ("$.error" ).value ("local - IllegalArgumentException" ));
76
+ }
77
+
78
+ @ Test
79
+ public void restGlobalExceptionHandlerMethod () throws Exception {
80
+ standaloneSetup (new RestPersonController ())
81
+ .setControllerAdvice (new RestGlobalExceptionHandler ()).build ()
82
+ .perform (get ("/person/Leia" ).accept (MediaType .APPLICATION_JSON ))
83
+ .andExpect (status ().isOk ())
84
+ .andExpect (jsonPath ("$.error" ).value ("global - IllegalStateException" ));
85
+ }
86
+
87
+ @ Test
88
+ public void restGlobalRestPersonControllerExceptionHandlerTakesPrecedenceOverGlobalExceptionHandler () throws Exception {
89
+ standaloneSetup (new RestPersonController ())
90
+ .setControllerAdvice (new RestGlobalExceptionHandler (), new RestPersonControllerExceptionHandler ()).build ()
91
+ .perform (get ("/person/Leia" ).accept (MediaType .APPLICATION_JSON ))
92
+ .andExpect (status ().isOk ())
93
+ .andExpect (jsonPath ("$.error" ).value ("globalPersonController - IllegalStateException" ));
94
+ }
95
+
96
+ @ Test // gh-25520
97
+ public void restNoHandlerFound () throws Exception {
98
+ standaloneSetup (new RestPersonController ())
99
+ .setControllerAdvice (new RestGlobalExceptionHandler (), new RestPersonControllerExceptionHandler ())
100
+ .addDispatcherServletCustomizer (dispatcherServlet -> dispatcherServlet .setThrowExceptionIfNoHandlerFound (true ))
101
+ .build ()
102
+ .perform (get ("/bogus" ).accept (MediaType .APPLICATION_JSON ))
103
+ .andExpect (status ().isOk ())
104
+ .andExpect (jsonPath ("$.error" ).value ("global - NoHandlerFoundException" ));
105
+ }
106
+
55
107
56
108
@ Controller
57
109
private static class PersonController {
58
110
59
- @ RequestMapping ( value = "/person/{name}" , method = RequestMethod . GET )
111
+ @ GetMapping ( "/person/{name}" )
60
112
public String show (@ PathVariable String name ) {
61
113
if (name .equals ("Clyde" )) {
62
114
throw new IllegalArgumentException ("simulated exception" );
@@ -73,15 +125,80 @@ public String handleException(IllegalArgumentException exception) {
73
125
}
74
126
}
75
127
76
-
77
128
@ ControllerAdvice
78
129
private static class GlobalExceptionHandler {
79
130
80
131
@ ExceptionHandler
81
132
public String handleException (IllegalStateException exception ) {
82
133
return "globalErrorView" ;
83
134
}
135
+ }
136
+
137
+ @ RestController
138
+ private static class RestPersonController {
139
+
140
+ @ GetMapping ("/person/{name}" )
141
+ Person get (@ PathVariable String name ) {
142
+ switch (name ) {
143
+ case "Luke" :
144
+ throw new IllegalArgumentException ();
145
+ case "Leia" :
146
+ throw new IllegalStateException ();
147
+ default :
148
+ return new Person ("Yoda" );
149
+ }
150
+ }
151
+
152
+ @ ExceptionHandler
153
+ Error handleException (IllegalArgumentException exception ) {
154
+ return new Error ("local - " + exception .getClass ().getSimpleName ());
155
+ }
156
+ }
157
+
158
+ @ RestControllerAdvice (assignableTypes = RestPersonController .class )
159
+ @ Order (Ordered .HIGHEST_PRECEDENCE )
160
+ private static class RestPersonControllerExceptionHandler {
161
+
162
+ @ ExceptionHandler
163
+ Error handleException (Throwable exception ) {
164
+ return new Error ("globalPersonController - " + exception .getClass ().getSimpleName ());
165
+ }
166
+ }
167
+
168
+ @ RestControllerAdvice
169
+ @ Order (Ordered .LOWEST_PRECEDENCE )
170
+ private static class RestGlobalExceptionHandler {
171
+
172
+ @ ExceptionHandler
173
+ Error handleException (Throwable exception ) {
174
+ return new Error ( "global - " + exception .getClass ().getSimpleName ());
175
+ }
176
+ }
84
177
178
+ static class Person {
179
+
180
+ private final String name ;
181
+
182
+ Person (String name ) {
183
+ this .name = name ;
184
+ }
185
+
186
+ public String getName () {
187
+ return name ;
188
+ }
189
+ }
190
+
191
+ static class Error {
192
+
193
+ private final String error ;
194
+
195
+ Error (String error ) {
196
+ this .error = error ;
197
+ }
198
+
199
+ public String getError () {
200
+ return error ;
201
+ }
85
202
}
86
203
87
204
}
0 commit comments