Honor spring.autoconfigure.exclude in test slices

Previously, the import selector for `@ImportAutoConfiguration` did not
consider the spring.autoconfigure.exclude property when determining
which auto-configurations to exclude. This meant that tests using a
slice that included a particular auto-configuration would include it
even if the application's configuration excluded it via
spring.autoconfigure.exclude. Confusingly, this could result in a
sliced test using an auto-configuration that would be excluded in a
broader `@SpringBootTest`.

This commit updates the ImportAutoConfigurationImportSelector to
consider the spring.autoconfigure.exclude property so that sliced tests
will use a subset of the auto-configurations that a `@SpringBootTest`
would use.

Fixes gh-21736
pull/22996/head
Andy Wilkinson 4 years ago
parent 1b85ce0769
commit 502ccb6586

@ -233,13 +233,23 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector,
return excluded;
}
private List<String> getExcludeAutoConfigurationsProperty() {
if (getEnvironment() instanceof ConfigurableEnvironment) {
Binder binder = Binder.get(getEnvironment());
/**
* Returns the auto-configurations excluded by the
* {@code spring.autoconfigure.exclude} property.
* @return excluded auto-configurations
* @since 2.3.2
*/
protected List<String> getExcludeAutoConfigurationsProperty() {
Environment environment = getEnvironment();
if (environment == null) {
return Collections.emptyList();
}
if (environment instanceof ConfigurableEnvironment) {
Binder binder = Binder.get(environment);
return binder.bind(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class).map(Arrays::asList)
.orElse(Collections.emptyList());
}
String[] excludes = getEnvironment().getProperty(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class);
String[] excludes = environment.getProperty(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class);
return (excludes != null) ? Arrays.asList(excludes) : Collections.emptyList();
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
@ -118,6 +118,7 @@ class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelec
}
}
}
exclusions.addAll(getExcludeAutoConfigurationsProperty());
return exclusions;
}

@ -25,22 +25,19 @@ import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration;
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.env.Environment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.util.ClassUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verifyNoInteractions;
/**
* Tests for {@link ImportAutoConfigurationImportSelector}.
@ -54,12 +51,10 @@ class ImportAutoConfigurationImportSelectorTests {
private final ConfigurableListableBeanFactory beanFactory = new DefaultListableBeanFactory();
@Mock
private Environment environment;
private final MockEnvironment environment = new MockEnvironment();
@BeforeEach
void setup() {
MockitoAnnotations.initMocks(this);
this.importSelector.setBeanFactory(this.beanFactory);
this.importSelector.setEnvironment(this.environment);
this.importSelector.setResourceLoader(new DefaultResourceLoader());
@ -80,10 +75,11 @@ class ImportAutoConfigurationImportSelectorTests {
}
@Test
void propertyExclusionsAreNotApplied() throws Exception {
AnnotationMetadata annotationMetadata = getAnnotationMetadata(ImportFreeMarker.class);
this.importSelector.selectImports(annotationMetadata);
verifyNoInteractions(this.environment);
void propertyExclusionsAreApplied() throws IOException {
this.environment.setProperty("spring.autoconfigure.exclude", FreeMarkerAutoConfiguration.class.getName());
AnnotationMetadata annotationMetadata = getAnnotationMetadata(MultipleImports.class);
String[] imports = this.importSelector.selectImports(annotationMetadata);
assertThat(imports).containsExactly(ThymeleafAutoConfiguration.class.getName());
}
@Test
@ -288,7 +284,9 @@ class ImportAutoConfigurationImportSelectorTests {
@interface MetaImportAutoConfiguration {
@AliasFor(annotation = ImportAutoConfiguration.class)
Class<?>[] exclude() default {};
Class<?>[] exclude() default {
};
}
@ -308,7 +306,9 @@ class ImportAutoConfigurationImportSelectorTests {
@interface SelfAnnotating {
@AliasFor(annotation = ImportAutoConfiguration.class, attribute = "exclude")
Class<?>[] excludeAutoConfiguration() default {};
Class<?>[] excludeAutoConfiguration() default {
};
}

Loading…
Cancel
Save