mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Remove static state from CF web endpoint integration tests
The mocks being static meant that their state was shared across each test in the class. This resulted in the tests being order dependent. This commit uses instance variables to hold the mocks, thereby ensuring that they're recreated for each test as part of the standard JUnit lifecycle. Closes gh-38363
This commit is contained in:
parent
9b8bcec33e
commit
c2156d6803
@ -75,22 +75,23 @@ import static org.mockito.Mockito.mock;
|
|||||||
*/
|
*/
|
||||||
class CloudFoundryWebFluxEndpointIntegrationTests {
|
class CloudFoundryWebFluxEndpointIntegrationTests {
|
||||||
|
|
||||||
private static ReactiveTokenValidator tokenValidator = mock(ReactiveTokenValidator.class);
|
private final ReactiveTokenValidator tokenValidator = mock(ReactiveTokenValidator.class);
|
||||||
|
|
||||||
private static ReactiveCloudFoundrySecurityService securityService = mock(
|
private final ReactiveCloudFoundrySecurityService securityService = mock(ReactiveCloudFoundrySecurityService.class);
|
||||||
ReactiveCloudFoundrySecurityService.class);
|
|
||||||
|
|
||||||
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner(
|
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner(
|
||||||
AnnotationConfigReactiveWebServerApplicationContext::new)
|
AnnotationConfigReactiveWebServerApplicationContext::new)
|
||||||
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class,
|
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class,
|
||||||
ReactiveWebServerFactoryAutoConfiguration.class))
|
ReactiveWebServerFactoryAutoConfiguration.class))
|
||||||
.withUserConfiguration(TestEndpointConfiguration.class)
|
.withUserConfiguration(TestEndpointConfiguration.class)
|
||||||
|
.withBean(ReactiveTokenValidator.class, () -> this.tokenValidator)
|
||||||
|
.withBean(ReactiveCloudFoundrySecurityService.class, () -> this.securityService)
|
||||||
.withPropertyValues("server.port=0");
|
.withPropertyValues("server.port=0");
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void operationWithSecurityInterceptorForbidden() {
|
void operationWithSecurityInterceptorForbidden() {
|
||||||
given(tokenValidator.validate(any())).willReturn(Mono.empty());
|
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.RESTRICTED));
|
given(this.securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||||
.uri("/cfApplication/test")
|
.uri("/cfApplication/test")
|
||||||
.accept(MediaType.APPLICATION_JSON)
|
.accept(MediaType.APPLICATION_JSON)
|
||||||
@ -102,8 +103,8 @@ class CloudFoundryWebFluxEndpointIntegrationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void operationWithSecurityInterceptorSuccess() {
|
void operationWithSecurityInterceptorSuccess() {
|
||||||
given(tokenValidator.validate(any())).willReturn(Mono.empty());
|
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.FULL));
|
given(this.securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.FULL));
|
||||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||||
.uri("/cfApplication/test")
|
.uri("/cfApplication/test")
|
||||||
.accept(MediaType.APPLICATION_JSON)
|
.accept(MediaType.APPLICATION_JSON)
|
||||||
@ -131,8 +132,8 @@ class CloudFoundryWebFluxEndpointIntegrationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void linksToOtherEndpointsWithFullAccess() {
|
void linksToOtherEndpointsWithFullAccess() {
|
||||||
given(tokenValidator.validate(any())).willReturn(Mono.empty());
|
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.FULL));
|
given(this.securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.FULL));
|
||||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||||
.uri("/cfApplication")
|
.uri("/cfApplication")
|
||||||
.accept(MediaType.APPLICATION_JSON)
|
.accept(MediaType.APPLICATION_JSON)
|
||||||
@ -169,7 +170,7 @@ class CloudFoundryWebFluxEndpointIntegrationTests {
|
|||||||
void linksToOtherEndpointsForbidden() {
|
void linksToOtherEndpointsForbidden() {
|
||||||
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(Reason.INVALID_TOKEN,
|
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(Reason.INVALID_TOKEN,
|
||||||
"invalid-token");
|
"invalid-token");
|
||||||
willThrow(exception).given(tokenValidator).validate(any());
|
willThrow(exception).given(this.tokenValidator).validate(any());
|
||||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||||
.uri("/cfApplication")
|
.uri("/cfApplication")
|
||||||
.accept(MediaType.APPLICATION_JSON)
|
.accept(MediaType.APPLICATION_JSON)
|
||||||
@ -181,8 +182,8 @@ class CloudFoundryWebFluxEndpointIntegrationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void linksToOtherEndpointsWithRestrictedAccess() {
|
void linksToOtherEndpointsWithRestrictedAccess() {
|
||||||
given(tokenValidator.validate(any())).willReturn(Mono.empty());
|
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.RESTRICTED));
|
given(this.securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||||
.uri("/cfApplication")
|
.uri("/cfApplication")
|
||||||
.accept(MediaType.APPLICATION_JSON)
|
.accept(MediaType.APPLICATION_JSON)
|
||||||
@ -232,7 +233,8 @@ class CloudFoundryWebFluxEndpointIntegrationTests {
|
|||||||
static class CloudFoundryReactiveConfiguration {
|
static class CloudFoundryReactiveConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
CloudFoundrySecurityInterceptor interceptor() {
|
CloudFoundrySecurityInterceptor interceptor(ReactiveTokenValidator tokenValidator,
|
||||||
|
ReactiveCloudFoundrySecurityService securityService) {
|
||||||
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService, "app-id");
|
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService, "app-id");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
|||||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||||
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
|
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
|
||||||
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
|
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
|
||||||
|
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
|
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
@ -70,13 +71,13 @@ import static org.mockito.Mockito.mock;
|
|||||||
*/
|
*/
|
||||||
class CloudFoundryMvcWebEndpointIntegrationTests {
|
class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||||
|
|
||||||
private static TokenValidator tokenValidator = mock(TokenValidator.class);
|
private final TokenValidator tokenValidator = mock(TokenValidator.class);
|
||||||
|
|
||||||
private static CloudFoundrySecurityService securityService = mock(CloudFoundrySecurityService.class);
|
private final CloudFoundrySecurityService securityService = mock(CloudFoundrySecurityService.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void operationWithSecurityInterceptorForbidden() {
|
void operationWithSecurityInterceptorForbidden() {
|
||||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.RESTRICTED);
|
given(this.securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.RESTRICTED);
|
||||||
load(TestEndpointConfiguration.class,
|
load(TestEndpointConfiguration.class,
|
||||||
(client) -> client.get()
|
(client) -> client.get()
|
||||||
.uri("/cfApplication/test")
|
.uri("/cfApplication/test")
|
||||||
@ -89,7 +90,7 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void operationWithSecurityInterceptorSuccess() {
|
void operationWithSecurityInterceptorSuccess() {
|
||||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.FULL);
|
given(this.securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.FULL);
|
||||||
load(TestEndpointConfiguration.class,
|
load(TestEndpointConfiguration.class,
|
||||||
(client) -> client.get()
|
(client) -> client.get()
|
||||||
.uri("/cfApplication/test")
|
.uri("/cfApplication/test")
|
||||||
@ -119,7 +120,7 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void linksToOtherEndpointsWithFullAccess() {
|
void linksToOtherEndpointsWithFullAccess() {
|
||||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.FULL);
|
given(this.securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.FULL);
|
||||||
load(TestEndpointConfiguration.class,
|
load(TestEndpointConfiguration.class,
|
||||||
(client) -> client.get()
|
(client) -> client.get()
|
||||||
.uri("/cfApplication")
|
.uri("/cfApplication")
|
||||||
@ -157,7 +158,7 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
|||||||
void linksToOtherEndpointsForbidden() {
|
void linksToOtherEndpointsForbidden() {
|
||||||
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(Reason.INVALID_TOKEN,
|
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(Reason.INVALID_TOKEN,
|
||||||
"invalid-token");
|
"invalid-token");
|
||||||
willThrow(exception).given(tokenValidator).validate(any());
|
willThrow(exception).given(this.tokenValidator).validate(any());
|
||||||
load(TestEndpointConfiguration.class,
|
load(TestEndpointConfiguration.class,
|
||||||
(client) -> client.get()
|
(client) -> client.get()
|
||||||
.uri("/cfApplication")
|
.uri("/cfApplication")
|
||||||
@ -170,7 +171,7 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void linksToOtherEndpointsWithRestrictedAccess() {
|
void linksToOtherEndpointsWithRestrictedAccess() {
|
||||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.RESTRICTED);
|
given(this.securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.RESTRICTED);
|
||||||
load(TestEndpointConfiguration.class,
|
load(TestEndpointConfiguration.class,
|
||||||
(client) -> client.get()
|
(client) -> client.get()
|
||||||
.uri("/cfApplication")
|
.uri("/cfApplication")
|
||||||
@ -198,26 +199,23 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
|||||||
.doesNotExist());
|
.doesNotExist());
|
||||||
}
|
}
|
||||||
|
|
||||||
private AnnotationConfigServletWebServerApplicationContext createApplicationContext(Class<?>... config) {
|
private void load(Class<?> configuration, Consumer<WebTestClient> clientConsumer) {
|
||||||
return new AnnotationConfigServletWebServerApplicationContext(config);
|
BiConsumer<ApplicationContext, WebTestClient> consumer = (context, client) -> clientConsumer.accept(client);
|
||||||
|
new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new)
|
||||||
|
.withUserConfiguration(configuration, CloudFoundryMvcConfiguration.class)
|
||||||
|
.withBean(TokenValidator.class, () -> this.tokenValidator)
|
||||||
|
.withBean(CloudFoundrySecurityService.class, () -> this.securityService)
|
||||||
|
.run((context) -> consumer.accept(context, WebTestClient.bindToServer()
|
||||||
|
.baseUrl("http://localhost:" + getPort(
|
||||||
|
(AnnotationConfigServletWebServerApplicationContext) context.getSourceApplicationContext()))
|
||||||
|
.responseTimeout(Duration.ofMinutes(5))
|
||||||
|
.build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPort(AnnotationConfigServletWebServerApplicationContext context) {
|
private int getPort(AnnotationConfigServletWebServerApplicationContext context) {
|
||||||
return context.getWebServer().getPort();
|
return context.getWebServer().getPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void load(Class<?> configuration, Consumer<WebTestClient> clientConsumer) {
|
|
||||||
BiConsumer<ApplicationContext, WebTestClient> consumer = (context, client) -> clientConsumer.accept(client);
|
|
||||||
try (AnnotationConfigServletWebServerApplicationContext context = createApplicationContext(configuration,
|
|
||||||
CloudFoundryMvcConfiguration.class)) {
|
|
||||||
consumer.accept(context,
|
|
||||||
WebTestClient.bindToServer()
|
|
||||||
.baseUrl("http://localhost:" + getPort(context))
|
|
||||||
.responseTimeout(Duration.ofMinutes(5))
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String mockAccessToken() {
|
private String mockAccessToken() {
|
||||||
return "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0b3B0YWwu"
|
return "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0b3B0YWwu"
|
||||||
+ "Y29tIiwiZXhwIjoxNDI2NDIwODAwLCJhd2Vzb21lIjp0cnVlfQ."
|
+ "Y29tIiwiZXhwIjoxNDI2NDIwODAwLCJhd2Vzb21lIjp0cnVlfQ."
|
||||||
@ -229,7 +227,8 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
|||||||
static class CloudFoundryMvcConfiguration {
|
static class CloudFoundryMvcConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
CloudFoundrySecurityInterceptor interceptor() {
|
CloudFoundrySecurityInterceptor interceptor(TokenValidator tokenValidator,
|
||||||
|
CloudFoundrySecurityService securityService) {
|
||||||
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService, "app-id");
|
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService, "app-id");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user