1
1
/*
2
- * Copyright 2012-2019 the original author or authors.
2
+ * Copyright 2012-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.
16
16
17
17
package org .springframework .boot .actuate .autoconfigure .web .servlet ;
18
18
19
+ import java .util .Collections ;
20
+ import java .util .Map ;
21
+ import java .util .function .Consumer ;
22
+
23
+ import javax .validation .Valid ;
24
+ import javax .validation .constraints .NotEmpty ;
25
+
19
26
import org .junit .jupiter .api .Test ;
20
27
21
28
import org .springframework .boot .actuate .autoconfigure .endpoint .EndpointAutoConfiguration ;
22
29
import org .springframework .boot .actuate .autoconfigure .endpoint .web .WebEndpointAutoConfiguration ;
23
30
import org .springframework .boot .actuate .autoconfigure .web .server .ManagementContextAutoConfiguration ;
24
31
import org .springframework .boot .actuate .endpoint .annotation .Endpoint ;
25
32
import org .springframework .boot .actuate .endpoint .annotation .ReadOperation ;
33
+ import org .springframework .boot .actuate .endpoint .web .annotation .RestControllerEndpoint ;
26
34
import org .springframework .boot .autoconfigure .AutoConfigurations ;
27
35
import org .springframework .boot .autoconfigure .web .servlet .DispatcherServletAutoConfiguration ;
28
36
import org .springframework .boot .autoconfigure .web .servlet .ServletWebServerFactoryAutoConfiguration ;
29
37
import org .springframework .boot .autoconfigure .web .servlet .error .ErrorMvcAutoConfiguration ;
38
+ import org .springframework .boot .test .context .assertj .AssertableWebApplicationContext ;
39
+ import org .springframework .boot .test .context .runner .ContextConsumer ;
30
40
import org .springframework .boot .test .context .runner .WebApplicationContextRunner ;
31
41
import org .springframework .boot .web .context .ServerPortInfoApplicationContextInitializer ;
32
42
import org .springframework .boot .web .servlet .context .AnnotationConfigServletWebServerApplicationContext ;
33
43
import org .springframework .http .MediaType ;
34
- import org .springframework .stereotype .Component ;
44
+ import org .springframework .web .bind .annotation .GetMapping ;
45
+ import org .springframework .web .bind .annotation .PostMapping ;
46
+ import org .springframework .web .bind .annotation .RequestBody ;
47
+ import org .springframework .web .bind .annotation .ResponseBody ;
35
48
import org .springframework .web .reactive .function .client .ClientResponse ;
36
49
import org .springframework .web .reactive .function .client .WebClient ;
37
50
41
54
* Integration tests for {@link WebMvcEndpointChildContextConfiguration}.
42
55
*
43
56
* @author Phillip Webb
57
+ * @author Scott Frederick
44
58
*/
45
59
class WebMvcEndpointChildContextConfigurationIntegrationTests {
46
60
61
+ final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner (
62
+ AnnotationConfigServletWebServerApplicationContext ::new )
63
+ .withConfiguration (AutoConfigurations .of (ServletWebServerFactoryAutoConfiguration .class ,
64
+ ManagementContextAutoConfiguration .class , ServletManagementContextAutoConfiguration .class ,
65
+ WebEndpointAutoConfiguration .class , EndpointAutoConfiguration .class ,
66
+ DispatcherServletAutoConfiguration .class , ErrorMvcAutoConfiguration .class ))
67
+ .withUserConfiguration (FailingEndpoint .class , FailingControllerEndpoint .class )
68
+ .withInitializer (new ServerPortInfoApplicationContextInitializer ())
69
+ .withPropertyValues ("server.port=0" , "management.server.port=0" ,
70
+ "management.endpoints.web.exposure.include=*" , "server.error.include-exception=true" );
71
+
47
72
@ Test // gh-17938
48
- void errorPageAndErrorControllerAreUsed () {
49
- new WebApplicationContextRunner (AnnotationConfigServletWebServerApplicationContext ::new )
50
- .withConfiguration (AutoConfigurations .of (ManagementContextAutoConfiguration .class ,
51
- ServletWebServerFactoryAutoConfiguration .class , ServletManagementContextAutoConfiguration .class ,
52
- WebEndpointAutoConfiguration .class , EndpointAutoConfiguration .class ,
53
- DispatcherServletAutoConfiguration .class , ErrorMvcAutoConfiguration .class ))
54
- .withUserConfiguration (FailingEndpoint .class )
55
- .withInitializer (new ServerPortInfoApplicationContextInitializer ()).withPropertyValues ("server.port=0" ,
56
- "management.server.port=0" , "management.endpoints.web.exposure.include=*" )
57
- .run ((context ) -> {
58
- String port = context .getEnvironment ().getProperty ("local.management.port" );
59
- WebClient client = WebClient .create ("http://localhost:" + port );
60
- ClientResponse response = client .get ().uri ("actuator/fail" ).accept (MediaType .APPLICATION_JSON )
61
- .exchange ().block ();
62
- assertThat (response .bodyToMono (String .class ).block ()).contains ("message\" :\" Epic Fail" );
63
- });
73
+ void errorEndpointIsUsedWithEndpoint () {
74
+ this .contextRunner .run (withWebTestClient ((client ) -> {
75
+ ClientResponse response = client .get ().uri ("actuator/fail" ).accept (MediaType .APPLICATION_JSON ).exchange ()
76
+ .block ();
77
+ Map <String , ?> body = getResponseBody (response );
78
+ assertThat (body ).hasEntrySatisfying ("exception" ,
79
+ (value ) -> assertThat (value ).asString ().contains ("IllegalStateException" ));
80
+ assertThat (body ).hasEntrySatisfying ("message" ,
81
+ (value ) -> assertThat (value ).asString ().contains ("Epic Fail" ));
82
+ }));
83
+ }
84
+
85
+ @ Test
86
+ void errorEndpointIsUsedWithRestControllerEndpoint () {
87
+ this .contextRunner .run (withWebTestClient ((client ) -> {
88
+ ClientResponse response = client .get ().uri ("actuator/failController" ).accept (MediaType .APPLICATION_JSON )
89
+ .exchange ().block ();
90
+ Map <String , ?> body = getResponseBody (response );
91
+ assertThat (body ).hasEntrySatisfying ("exception" ,
92
+ (value ) -> assertThat (value ).asString ().contains ("IllegalStateException" ));
93
+ assertThat (body ).hasEntrySatisfying ("message" ,
94
+ (value ) -> assertThat (value ).asString ().contains ("Epic Fail" ));
95
+ }));
96
+ }
97
+
98
+ @ Test
99
+ void errorEndpointIsUsedWithRestControllerEndpointOnBindingError () {
100
+ this .contextRunner .run (withWebTestClient ((client ) -> {
101
+ ClientResponse response = client .post ().uri ("actuator/failController" )
102
+ .bodyValue (Collections .singletonMap ("content" , "" )).accept (MediaType .APPLICATION_JSON ).exchange ()
103
+ .block ();
104
+ Map <String , ?> body = getResponseBody (response );
105
+ assertThat (body ).hasEntrySatisfying ("exception" ,
106
+ (value ) -> assertThat (value ).asString ().contains ("MethodArgumentNotValidException" ));
107
+ assertThat (body ).hasEntrySatisfying ("message" ,
108
+ (value ) -> assertThat (value ).asString ().contains ("Validation failed" ));
109
+ assertThat (body ).hasEntrySatisfying ("errors" , (value ) -> assertThat (value ).asList ().isNotEmpty ());
110
+ }));
111
+ }
112
+
113
+ private ContextConsumer <AssertableWebApplicationContext > withWebTestClient (Consumer <WebClient > webClient ) {
114
+ return (context ) -> {
115
+ String port = context .getEnvironment ().getProperty ("local.management.port" );
116
+ WebClient client = WebClient .create ("http://localhost:" + port );
117
+ webClient .accept (client );
118
+ };
119
+ }
120
+
121
+ @ SuppressWarnings ("unchecked" )
122
+ private Map <String , ?> getResponseBody (ClientResponse response ) {
123
+ return (Map <String , ?>) response .bodyToMono (Map .class ).block ();
64
124
}
65
125
66
- @ Component
67
126
@ Endpoint (id = "fail" )
68
127
static class FailingEndpoint {
69
128
@@ -74,4 +133,35 @@ String fail() {
74
133
75
134
}
76
135
136
+ @ RestControllerEndpoint (id = "failController" )
137
+ static class FailingControllerEndpoint {
138
+
139
+ @ GetMapping
140
+ String fail () {
141
+ throw new IllegalStateException ("Epic Fail" );
142
+ }
143
+
144
+ @ PostMapping (produces = "application/json" )
145
+ @ ResponseBody
146
+ String bodyValidation (@ Valid @ RequestBody TestBody body ) {
147
+ return body .getContent ();
148
+ }
149
+
150
+ }
151
+
152
+ public static class TestBody {
153
+
154
+ @ NotEmpty
155
+ private String content ;
156
+
157
+ public String getContent () {
158
+ return this .content ;
159
+ }
160
+
161
+ public void setContent (String content ) {
162
+ this .content = content ;
163
+ }
164
+
165
+ }
166
+
77
167
}
0 commit comments