Commit a3e94f44 authored by Stephane Nicoll's avatar Stephane Nicoll

Harmonize component scan in slice tests

This commit updates ConfigurationPropertiesScanRegistrar to apply the
same component scan filters than the ones applied on standard classpath
scanning.

As a result, configuration properties scanning is automatically disabled
in slice tests and can be included by an explicit import or a dedicated
TypeFilter implementation if necessary.

Closes gh-16659
parent 6d9a54a2
/*
* Copyright 2012-2019 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
*
* https://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.autoconfigure.web.client;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
/**
* Example {@link ConfigurationProperties} used to test the use of configuration
* properties scan with sliced test.
*
* @author Stephane Nicoll
*/
@ConfigurationProperties("example")
public class ExampleProperties {
private final String name;
public ExampleProperties(@DefaultValue("test") String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
......@@ -53,6 +53,12 @@ class RestClientTestNoComponentIntegrationTests {
.isThrownBy(() -> this.applicationContext.getBean(ExampleRestClient.class));
}
@Test
void examplePropertiesIsNotInjected() {
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
.isThrownBy(() -> this.applicationContext.getBean(ExampleProperties.class));
}
@Test
void manuallyCreateBean() {
ExampleRestClient client = new ExampleRestClient(this.restTemplateBuilder);
......
/*
* Copyright 2012-2019 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
*
* https://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.autoconfigure.web.client;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link RestClientTest @RestClientTest} with a {@link ConfigurationProperties}
* annotated type.
*
* @author Stephane Nicoll
*/
@RestClientTest(components = ExampleProperties.class, properties = "example.name=Hello")
class RestClientTestWithConfigurationPropertiesIntegrationTests {
@Autowired
private ApplicationContext applicationContext;
@Test
void configurationPropertiesCanBeAddedAsComponent() {
assertThat(this.applicationContext.getBeansOfType(ExampleProperties.class).keySet())
.containsOnly("example-org.springframework.boot.test.autoconfigure.web.client.ExampleProperties");
assertThat(this.applicationContext.getBean(ExampleProperties.class).getName()).isEqualTo("Hello");
}
}
......@@ -22,6 +22,7 @@ import java.util.Set;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
......@@ -82,6 +83,9 @@ class ConfigurationPropertiesScanRegistrar
scanner.setEnvironment(this.environment);
scanner.setResourceLoader(this.resourceLoader);
scanner.addIncludeFilter(new AnnotationTypeFilter(ConfigurationProperties.class));
TypeExcludeFilter typeExcludeFilter = new TypeExcludeFilter();
typeExcludeFilter.setBeanFactory(beanFactory);
scanner.addExcludeFilter(typeExcludeFilter);
for (String basePackage : packages) {
if (StringUtils.hasText(basePackage)) {
scan(beanFactory, registry, scanner, basePackage);
......
......@@ -87,10 +87,13 @@ class ConfigurationPropertiesScanRegistrarTests {
.isFalse();
BeanDefinition aDefinition = beanFactory.getBeanDefinition(
"a-org.springframework.boot.context.properties.scan.valid.a.AScanConfiguration$AProperties");
BeanDefinition bDefinition = beanFactory.getBeanDefinition(
"b-org.springframework.boot.context.properties.scan.valid.b.BScanConfiguration$BProperties");
BeanDefinition bFirstDefinition = beanFactory.getBeanDefinition(
"b.first-org.springframework.boot.context.properties.scan.valid.b.BScanConfiguration$BFirstProperties");
BeanDefinition bSecondDefinition = beanFactory.getBeanDefinition(
"b.second-org.springframework.boot.context.properties.scan.valid.b.BScanConfiguration$BSecondProperties");
assertThat(aDefinition).isExactlyInstanceOf(GenericBeanDefinition.class);
assertThat(bDefinition).isExactlyInstanceOf(GenericBeanDefinition.class);
assertThat(bFirstDefinition).isExactlyInstanceOf(GenericBeanDefinition.class);
assertThat(bSecondDefinition).isExactlyInstanceOf(GenericBeanDefinition.class);
}
@Test
......
......@@ -16,14 +16,23 @@
package org.springframework.boot.context.properties;
import java.io.IOException;
import java.util.Objects;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.boot.context.properties.scan.valid.a.AScanConfiguration;
import org.springframework.boot.context.properties.scan.valid.b.BScanConfiguration.BFirstProperties;
import org.springframework.boot.context.properties.scan.valid.b.BScanConfiguration.BProperties;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AssignableTypeFilter;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
......@@ -89,6 +98,23 @@ class ConfigurationPropertiesScanTests {
.isFalse();
}
@Test
void scanImportBeanRegistrarShouldUsePackageName() {
load(TestAnotherPackageConfiguration.class);
assertThat(this.context.getBeanNamesForType(BProperties.class)).containsOnly(
"b.first-org.springframework.boot.context.properties.scan.valid.b.BScanConfiguration$BFirstProperties",
"b.second-org.springframework.boot.context.properties.scan.valid.b.BScanConfiguration$BSecondProperties");
}
@Test
void scanImportBeanRegistrarShouldApplyTypeExcludeFilter() {
this.context.getBeanFactory().registerSingleton("filter", new ConfigurationPropertiesTestTypeExcludeFilter());
this.context.register(TestAnotherPackageConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeanNamesForType(BProperties.class)).containsOnly(
"b.first-org.springframework.boot.context.properties.scan.valid.b.BScanConfiguration$BFirstProperties");
}
private void load(Class<?>... classes) {
this.context.register(classes);
this.context.refresh();
......@@ -99,4 +125,30 @@ class ConfigurationPropertiesScanTests {
}
@ConfigurationPropertiesScan(basePackages = "org.springframework.boot.context.properties.scan.valid.b")
static class TestAnotherPackageConfiguration {
}
static class ConfigurationPropertiesTestTypeExcludeFilter extends TypeExcludeFilter {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
AssignableTypeFilter typeFilter = new AssignableTypeFilter(BFirstProperties.class);
return !typeFilter.match(metadataReader, metadataReaderFactory);
}
@Override
public boolean equals(Object o) {
return (this == o);
}
@Override
public int hashCode() {
return Objects.hash(42);
}
}
}
......@@ -19,11 +19,21 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author Madhura Bhave
* @author Stephane Nicoll
*/
public class BScanConfiguration {
@ConfigurationProperties(prefix = "b")
static class BProperties {
public interface BProperties {
}
@ConfigurationProperties(prefix = "b.first")
public static class BFirstProperties implements BProperties {
}
@ConfigurationProperties(prefix = "b.second")
public static class BSecondProperties implements BProperties {
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment