Allow custom WebTestClient beans
Update `@SpringBootTest` `WebTestClient` support so that the bean definition is only registered when the user has not defined or auto-configured their own. See gh-10556
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -57,8 +57,9 @@ import org.springframework.web.context.WebApplicationContext;
|
||||
* {@link WebEnvironment#DEFINED_PORT defined} or {@link WebEnvironment#RANDOM_PORT
|
||||
* random} port.</li>
|
||||
* <li>Registers a {@link org.springframework.boot.test.web.client.TestRestTemplate
|
||||
* TestRestTemplate} bean for use in web tests that are using a fully running web server.
|
||||
* </li>
|
||||
* TestRestTemplate} and/or
|
||||
* {@link org.springframework.test.web.reactive.server.WebTestClient WebTestClient} bean
|
||||
* for use in web tests that are using a fully running web server.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Phillip Webb
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,15 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.test.web.reactive;
|
||||
package org.springframework.boot.test.web.reactive.server;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.web.codec.CodecCustomizer;
|
||||
@@ -30,6 +36,8 @@ import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFac
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.test.context.ContextCustomizer;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
@@ -63,8 +71,11 @@ class WebTestClientContextCustomizer implements ContextCustomizer {
|
||||
|
||||
private void registerWebTestClient(ConfigurableApplicationContext context,
|
||||
BeanDefinitionRegistry registry) {
|
||||
registry.registerBeanDefinition(WebTestClient.class.getName(),
|
||||
new RootBeanDefinition(WebTestClientFactory.class));
|
||||
RootBeanDefinition definition = new RootBeanDefinition(
|
||||
WebTestClientRegistrar.class);
|
||||
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
registry.registerBeanDefinition(WebTestClientRegistrar.class.getName(),
|
||||
definition);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,6 +88,45 @@ class WebTestClientContextCustomizer implements ContextCustomizer {
|
||||
return (obj != null && obj.getClass() == getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link BeanDefinitionRegistryPostProcessor} that runs after the
|
||||
* {@link ConfigurationClassPostProcessor} and add a {@link WebTestClientFactory} bean
|
||||
* definition when a {@link WebTestClient} hasn't already been registered.
|
||||
*/
|
||||
private static class WebTestClientRegistrar
|
||||
implements BeanDefinitionRegistryPostProcessor, Ordered, BeanFactoryAware {
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
|
||||
throws BeansException {
|
||||
if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
(ListableBeanFactory) this.beanFactory,
|
||||
WebTestClient.class).length == 0) {
|
||||
registry.registerBeanDefinition(WebTestClient.class.getName(),
|
||||
new RootBeanDefinition(WebTestClientFactory.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
|
||||
throws BeansException {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} used to create and configure a {@link WebTestClient}.
|
||||
*/
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.test.web.reactive;
|
||||
package org.springframework.boot.test.web.reactive.server;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.util.ClassUtils;
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class WebTestClientContextCustomizerFactory implements ContextCustomizerFactory {
|
||||
class WebTestClientContextCustomizerFactory implements ContextCustomizerFactory {
|
||||
|
||||
private static final String WEB_TEST_CLIENT_CLASS = "org.springframework.web.reactive.function.client.WebClient";
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Spring Boot support for testing Spring WebFlux server endpoints via
|
||||
* {@link org.springframework.test.web.reactive.server.WebTestClient}.
|
||||
*/
|
||||
package org.springframework.boot.test.web.reactive.server;
|
||||
@@ -5,7 +5,7 @@ org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizerFacto
|
||||
org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory,\
|
||||
org.springframework.boot.test.mock.mockito.MockitoContextCustomizerFactory,\
|
||||
org.springframework.boot.test.web.client.TestRestTemplateTestContextCustomizerFactory,\
|
||||
org.springframework.boot.test.web.reactive.WebTestClientContextCustomizerFactory
|
||||
org.springframework.boot.test.web.reactive.server.WebTestClientContextCustomizerFactory
|
||||
|
||||
# Test Execution Listeners
|
||||
org.springframework.test.context.TestExecutionListener=\
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.test.web.reactive.server;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.context.annotation.ImportSelector;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* {@link ImportSelector} to check no {@link WebTestClient} definition is registered when
|
||||
* config classes are processed.
|
||||
*/
|
||||
class NoWebTestClientBeanChecker implements ImportSelector, BeanFactoryAware {
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
assertThat(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
(ListableBeanFactory) beanFactory, WebTestClient.class)).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.test.web.reactive.server;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
/**
|
||||
* Integration test for {@link WebTestClientContextCustomizer}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "spring.main.web-application-type=reactive")
|
||||
@DirtiesContext
|
||||
public class WebTestClientContextCustomizerIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private WebTestClient webTestClient;
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
this.webTestClient.get().uri("/").exchange().expectBody(String.class)
|
||||
.isEqualTo("hello");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ TestHandler.class, NoWebTestClientBeanChecker.class })
|
||||
static class TestConfig {
|
||||
|
||||
@Bean
|
||||
public TomcatReactiveWebServerFactory webServerFactory() {
|
||||
return new TomcatReactiveWebServerFactory(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestHandler implements HttpHandler {
|
||||
|
||||
private static final DefaultDataBufferFactory factory = new DefaultDataBufferFactory();
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
return response.writeWith(Mono.just(factory.wrap("hello".getBytes())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2012-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.test.web.reactive.server;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Integration test for {@link WebTestClientContextCustomizer} with a custom
|
||||
* {@link WebTestClient} bean.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "spring.main.web-application-type=reactive")
|
||||
@DirtiesContext
|
||||
public class WebTestClientContextCustomizerWithOverrideIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private WebTestClient webTestClient;
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
assertThat(this.webTestClient).isInstanceOf(CustomWebTestClient.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ TestHandler.class, NoWebTestClientBeanChecker.class })
|
||||
static class TestConfig {
|
||||
|
||||
@Bean
|
||||
public TomcatReactiveWebServerFactory webServerFactory() {
|
||||
return new TomcatReactiveWebServerFactory(0);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebTestClient webTestClient() {
|
||||
return mock(CustomWebTestClient.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestHandler implements HttpHandler {
|
||||
|
||||
private static final DefaultDataBufferFactory factory = new DefaultDataBufferFactory();
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
return response.writeWith(Mono.just(factory.wrap("hello".getBytes())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface CustomWebTestClient extends WebTestClient {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user