Skip to content

Commit

Permalink
Honor spring.autoconfigure.exclude in test slices
Browse files Browse the repository at this point in the history
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
  • Loading branch information
wilkinsona committed Jul 8, 2020
1 parent 1b85ce0 commit 502ccb6
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -233,13 +233,23 @@ protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttri
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();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -118,6 +118,7 @@ protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttri
}
}
}
exclusions.addAll(getExcludeAutoConfigurationsProperty());
return exclusions;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,19 @@

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}.
Expand All @@ -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());
Expand All @@ -80,10 +75,11 @@ void importsAreSelectedUsingClassesAttribute() throws Exception {
}

@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
Expand Down Expand Up @@ -288,7 +284,9 @@ static class ImportMetaAutoConfigurationExcludeWithUnrelatedTwo {
@interface MetaImportAutoConfiguration {

@AliasFor(annotation = ImportAutoConfiguration.class)
Class<?>[] exclude() default {};
Class<?>[] exclude() default {

};

}

Expand All @@ -308,7 +306,9 @@ static class ImportMetaAutoConfigurationExcludeWithUnrelatedTwo {
@interface SelfAnnotating {

@AliasFor(annotation = ImportAutoConfiguration.class, attribute = "exclude")
Class<?>[] excludeAutoConfiguration() default {};
Class<?>[] excludeAutoConfiguration() default {

};

}

Expand Down

0 comments on commit 502ccb6

Please sign in to comment.