Skip to content

Commit

Permalink
Inherit enclosing class's configuration in nested tests
Browse files Browse the repository at this point in the history
Fixes gh-12470
  • Loading branch information
wilkinsona committed Oct 28, 2020
1 parent b0a1c2a commit 6b437ec
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 48 deletions.
@@ -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 All @@ -21,12 +21,12 @@
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.TestContextAnnotationUtils;
import org.springframework.test.context.TestContextAnnotationUtils.AnnotationDescriptor;

/**
* {@link ContextCustomizerFactory} to support
Expand All @@ -39,8 +39,9 @@ class OverrideAutoConfigurationContextCustomizerFactory implements ContextCustom
@Override
public ContextCustomizer createContextCustomizer(Class<?> testClass,
List<ContextConfigurationAttributes> configurationAttributes) {
boolean enabled = MergedAnnotations.from(testClass, SearchStrategy.TYPE_HIERARCHY)
.get(OverrideAutoConfiguration.class).getValue("enabled", Boolean.class).orElse(true);
AnnotationDescriptor<OverrideAutoConfiguration> descriptor = TestContextAnnotationUtils
.findAnnotationDescriptor(testClass, OverrideAutoConfiguration.class);
boolean enabled = (descriptor != null) ? descriptor.getAnnotation().enabled() : true;
return !enabled ? new DisableAutoConfigurationContextCustomizer() : null;
}

Expand Down
Expand Up @@ -20,12 +20,11 @@

import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.TestContextAnnotationUtils;

/**
* {@link ContextCustomizerFactory} that globally disables metrics export unless
Expand All @@ -38,8 +37,8 @@ class MetricsExportContextCustomizerFactory implements ContextCustomizerFactory
@Override
public ContextCustomizer createContextCustomizer(Class<?> testClass,
List<ContextConfigurationAttributes> configAttributes) {
boolean disableMetricsExport = !MergedAnnotations.from(testClass, SearchStrategy.TYPE_HIERARCHY)
.get(AutoConfigureMetrics.class).isPresent();
boolean disableMetricsExport = TestContextAnnotationUtils.findAnnotationDescriptor(testClass,
AutoConfigureMetrics.class) == null;
return disableMetricsExport ? new DisableMetricExportContextCustomizer() : null;
}

Expand Down
@@ -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 All @@ -22,10 +22,11 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory;
import org.springframework.test.context.TestContextAnnotationUtils;
import org.springframework.test.context.TestContextAnnotationUtils.AnnotationDescriptor;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;

Expand All @@ -41,9 +42,11 @@ class ImportsContextCustomizerFactory implements ContextCustomizerFactory {
@Override
public ContextCustomizer createContextCustomizer(Class<?> testClass,
List<ContextConfigurationAttributes> configAttributes) {
if (MergedAnnotations.from(testClass, SearchStrategy.TYPE_HIERARCHY).isPresent(Import.class)) {
assertHasNoBeanMethods(testClass);
return new ImportsContextCustomizer(testClass);
AnnotationDescriptor<Import> descriptor = TestContextAnnotationUtils.findAnnotationDescriptor(testClass,
Import.class);
if (descriptor != null) {
assertHasNoBeanMethods(descriptor.getRootDeclaringClass());
return new ImportsContextCustomizer(descriptor.getRootDeclaringClass());
}
return null;
}
Expand Down
Expand Up @@ -46,6 +46,8 @@
import org.springframework.test.context.ContextLoader;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestContextAnnotationUtils;
import org.springframework.test.context.TestContextAnnotationUtils.AnnotationDescriptor;
import org.springframework.test.context.TestContextBootstrapper;
import org.springframework.test.context.TestExecutionListener;
import org.springframework.test.context.support.DefaultTestContextBootstrapper;
Expand Down Expand Up @@ -318,8 +320,12 @@ protected String[] getProperties(Class<?> testClass) {
}

protected SpringBootTest getAnnotation(Class<?> testClass) {
return MergedAnnotations.from(testClass, SearchStrategy.INHERITED_ANNOTATIONS).get(SpringBootTest.class)
.synthesize(MergedAnnotation::isPresent).orElse(null);
AnnotationDescriptor<SpringBootTest> descriptor = TestContextAnnotationUtils.findAnnotationDescriptor(testClass,
SpringBootTest.class);
if (descriptor != null) {
return descriptor.getAnnotation();
}
return null;
}

protected void verifyConfiguration(Class<?> testClass) {
Expand Down
Expand Up @@ -18,9 +18,10 @@

import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.TestContextAnnotationUtils;
import org.springframework.test.context.TestContextAnnotationUtils.AnnotationDescriptor;

/**
* {@link ContextCustomizer} to track the web environment that is used in a
Expand All @@ -35,8 +36,9 @@ class SpringBootTestWebEnvironment implements ContextCustomizer {
private final WebEnvironment webEnvironment;

SpringBootTestWebEnvironment(Class<?> testClass) {
this.webEnvironment = MergedAnnotations.from(testClass, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY)
.get(SpringBootTest.class).getValue("webEnvironment", WebEnvironment.class).orElse(null);
AnnotationDescriptor<SpringBootTest> descriptor = TestContextAnnotationUtils.findAnnotationDescriptor(testClass,
SpringBootTest.class);
this.webEnvironment = (descriptor != null) ? descriptor.getAnnotation().webEnvironment() : null;
}

@Override
Expand Down
@@ -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 All @@ -21,6 +21,7 @@
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory;
import org.springframework.test.context.TestContextAnnotationUtils;

/**
* A {@link ContextCustomizerFactory} to add Mockito support.
Expand All @@ -35,8 +36,15 @@ public ContextCustomizer createContextCustomizer(Class<?> testClass,
// We gather the explicit mock definitions here since they form part of the
// MergedContextConfiguration key. Different mocks need to have a different key.
DefinitionsParser parser = new DefinitionsParser();
parser.parse(testClass);
parseDefinitions(testClass, parser);
return new MockitoContextCustomizer(parser.getDefinitions());
}

private void parseDefinitions(Class<?> testClass, DefinitionsParser parser) {
parser.parse(testClass);
if (TestContextAnnotationUtils.searchEnclosingClass(testClass)) {
parseDefinitions(testClass.getEnclosingClass(), parser);
}
}

}
@@ -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 @@ -29,7 +29,6 @@
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.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate.HttpClientOption;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory;
Expand All @@ -38,11 +37,10 @@
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.TestContextAnnotationUtils;
import org.springframework.test.context.TestContextAnnotationUtils.AnnotationDescriptor;

/**
* {@link ContextCustomizer} for {@link TestRestTemplate}.
Expand All @@ -55,10 +53,9 @@ class TestRestTemplateContextCustomizer implements ContextCustomizer {
@Override
public void customizeContext(ConfigurableApplicationContext context,
MergedContextConfiguration mergedContextConfiguration) {
MergedAnnotation<?> annotation = MergedAnnotations
.from(mergedContextConfiguration.getTestClass(), SearchStrategy.INHERITED_ANNOTATIONS)
.get(SpringBootTest.class);
if (annotation.getEnum("webEnvironment", WebEnvironment.class).isEmbedded()) {
AnnotationDescriptor<SpringBootTest> springBootTest = TestContextAnnotationUtils
.findAnnotationDescriptor(mergedContextConfiguration.getTestClass(), SpringBootTest.class);
if (springBootTest.getAnnotation().webEnvironment().isEmbedded()) {
registerTestRestTemplate(context);
}
}
Expand Down
@@ -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 All @@ -19,11 +19,11 @@
import java.util.List;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory;
import org.springframework.test.context.TestContextAnnotationUtils;
import org.springframework.test.context.TestContextAnnotationUtils.AnnotationDescriptor;

/**
* {@link ContextCustomizerFactory} for {@link TestRestTemplate}.
Expand All @@ -36,8 +36,9 @@ class TestRestTemplateContextCustomizerFactory implements ContextCustomizerFacto
@Override
public ContextCustomizer createContextCustomizer(Class<?> testClass,
List<ContextConfigurationAttributes> configAttributes) {
MergedAnnotations annotations = MergedAnnotations.from(testClass, SearchStrategy.INHERITED_ANNOTATIONS);
if (annotations.isPresent(SpringBootTest.class)) {
AnnotationDescriptor<SpringBootTest> springBootTest = TestContextAnnotationUtils
.findAnnotationDescriptor(testClass, SpringBootTest.class);
if (springBootTest != null) {
return new TestRestTemplateContextCustomizer();
}
return null;
Expand Down
@@ -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 @@ -31,19 +31,17 @@
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.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.codec.CodecCustomizer;
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory;
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.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.TestContextAnnotationUtils;
import org.springframework.test.context.TestContextAnnotationUtils.AnnotationDescriptor;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.util.CollectionUtils;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
Expand All @@ -57,9 +55,9 @@ class WebTestClientContextCustomizer implements ContextCustomizer {

@Override
public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
MergedAnnotation<?> annotation = MergedAnnotations
.from(mergedConfig.getTestClass(), SearchStrategy.INHERITED_ANNOTATIONS).get(SpringBootTest.class);
if (annotation.getEnum("webEnvironment", WebEnvironment.class).isEmbedded()) {
AnnotationDescriptor<SpringBootTest> springBootTest = TestContextAnnotationUtils
.findAnnotationDescriptor(mergedConfig.getTestClass(), SpringBootTest.class);
if (springBootTest.getAnnotation().webEnvironment().isEmbedded()) {
registerWebTestClient(context);
}
}
Expand Down
@@ -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 All @@ -19,11 +19,11 @@
import java.util.List;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory;
import org.springframework.test.context.TestContextAnnotationUtils;
import org.springframework.test.context.TestContextAnnotationUtils.AnnotationDescriptor;
import org.springframework.util.ClassUtils;

/**
Expand All @@ -38,8 +38,9 @@ class WebTestClientContextCustomizerFactory implements ContextCustomizerFactory
@Override
public ContextCustomizer createContextCustomizer(Class<?> testClass,
List<ContextConfigurationAttributes> configAttributes) {
MergedAnnotations annotations = MergedAnnotations.from(testClass, SearchStrategy.INHERITED_ANNOTATIONS);
if (isWebClientPresent() && annotations.isPresent(SpringBootTest.class)) {
AnnotationDescriptor<SpringBootTest> springBootTest = TestContextAnnotationUtils
.findAnnotationDescriptor(testClass, SpringBootTest.class);
if (springBootTest != null) {
return new WebTestClientContextCustomizer();
}
return null;
Expand Down

0 comments on commit 6b437ec

Please sign in to comment.