From c849cafc1b4c356f36822732f882699586991836 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 6 Mar 2025 10:55:52 +0000 Subject: [PATCH] Further improve independence of core auto-configuration tests See gh-44513 --- .../ConditionEvaluationReportTests.java | 61 +++++++++++++------ .../ConditionEvaluationReportLoggerTests.java | 30 ++++++++- ...nEvaluationReportLoggingListenerTests.java | 41 ++++++++++--- 3 files changed, 104 insertions(+), 28 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionEvaluationReportTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionEvaluationReportTests.java index 6ac69ca71b1..bf8154c22fa 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionEvaluationReportTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionEvaluationReportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 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. @@ -16,6 +16,7 @@ package org.springframework.boot.autoconfigure.condition; +import java.time.Duration; import java.util.Iterator; import java.util.Map; @@ -27,12 +28,12 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport.ConditionAndOutcome; import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport.ConditionAndOutcomes; import org.springframework.boot.autoconfigure.condition.config.UniqueShortNameAutoConfiguration; import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportMessage; -import org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -41,7 +42,6 @@ import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ConfigurationCondition; -import org.springframework.context.annotation.Import; import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.util.ClassUtils; @@ -163,7 +163,17 @@ class ConditionEvaluationReportTests { void springBootConditionPopulatesReport() { ConditionEvaluationReport report = ConditionEvaluationReport .get(new AnnotationConfigApplicationContext(Config.class).getBeanFactory()); - assertThat(report.getConditionAndOutcomesBySource()).isNotEmpty(); + assertThat(report.getUnconditionalClasses()).containsExactly(UnconditionalAutoConfiguration.class.getName()); + assertThat(report.getConditionAndOutcomesBySource()).containsOnlyKeys(MatchingAutoConfiguration.class.getName(), + NonMatchingAutoConfiguration.class.getName()); + assertThat(report.getConditionAndOutcomesBySource().get(MatchingAutoConfiguration.class.getName())) + .satisfies((outcomes) -> assertThat(outcomes).extracting(ConditionAndOutcome::getOutcome) + .extracting(ConditionOutcome::isMatch) + .containsOnly(true)); + assertThat(report.getConditionAndOutcomesBySource().get(NonMatchingAutoConfiguration.class.getName())) + .satisfies((outcomes) -> assertThat(outcomes).extracting(ConditionAndOutcome::getOutcome) + .extracting(ConditionOutcome::isMatch) + .containsOnly(false)); } @Test @@ -230,18 +240,6 @@ class ConditionEvaluationReportTests { context.close(); } - @Configuration(proxyBeanMethods = false) - @Import(WebMvcAutoConfiguration.class) - static class Config { - - } - - @Configuration(proxyBeanMethods = false) - @Import(MultipartAutoConfiguration.class) - static class DuplicateConfig { - - } - @Configuration(proxyBeanMethods = false) @Conditional({ ConditionEvaluationReportTests.MatchParseCondition.class, ConditionEvaluationReportTests.NoMatchBeanCondition.class }) @@ -315,4 +313,33 @@ class ConditionEvaluationReportTests { } + @Configuration(proxyBeanMethods = false) + @ImportAutoConfiguration({ MatchingAutoConfiguration.class, NonMatchingAutoConfiguration.class, + UnconditionalAutoConfiguration.class }) + static class Config { + + } + + @AutoConfiguration + @ConditionalOnProperty(name = "com.example.property", matchIfMissing = true) + static class MatchingAutoConfiguration { + + } + + @AutoConfiguration + @ConditionalOnBean(Duration.class) + static class NonMatchingAutoConfiguration { + + } + + @AutoConfiguration + static class UnconditionalAutoConfiguration { + + @Bean + String example() { + return "example"; + } + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggerTests.java index c728158876e..28d8fdf3c28 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 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. @@ -16,6 +16,7 @@ package org.springframework.boot.autoconfigure.logging; +import java.time.Duration; import java.util.Arrays; import ch.qos.logback.classic.Level; @@ -25,12 +26,16 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport; -import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListenerTests.Config; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.logging.LogLevel; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Configuration; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; @@ -104,7 +109,8 @@ class ConditionEvaluationReportLoggerTests { ConditionEvaluationReport.get(context.getBeanFactory()).recordExclusions(Arrays.asList("com.foo.Bar")); context.refresh(); withDebugLogging(() -> logger.logReport(false)); - assertThat(output).contains("not a servlet web application (OnWebApplicationCondition)"); + assertThat(output).contains("did not find any beans of type java.time.Duration (OnBeanCondition)") + .contains("@ConditionalOnProperty (com.example.property) matched (OnPropertyCondition)"); } } @@ -121,4 +127,22 @@ class ConditionEvaluationReportLoggerTests { } } + @Configuration(proxyBeanMethods = false) + @ImportAutoConfiguration({ MatchingAutoConfiguration.class, NonMatchingAutoConfiguration.class }) + static class Config { + + } + + @AutoConfiguration + @ConditionalOnProperty(name = "com.example.property", matchIfMissing = true) + static class MatchingAutoConfiguration { + + } + + @AutoConfiguration + @ConditionalOnBean(Duration.class) + static class NonMatchingAutoConfiguration { + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListenerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListenerTests.java index 0c2d48f743f..66d8d44a194 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListenerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportLoggingListenerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 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. @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.logging; +import java.time.Duration; + import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.LoggerContext; @@ -24,10 +26,11 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport; -import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; -import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration; -import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.event.ApplicationFailedEvent; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; @@ -35,7 +38,6 @@ import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebAp import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.mock.web.MockServletContext; import static org.assertj.core.api.Assertions.assertThat; @@ -126,14 +128,15 @@ class ConditionEvaluationReportLoggingListenerTests { } @Configuration(proxyBeanMethods = false) - @Import({ WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class }) + @ImportAutoConfiguration({ MatchingAutoConfiguration.class, NonMatchingAutoConfiguration.class, + UnconditionalAutoConfiguration.class }) static class Config { } @Configuration(proxyBeanMethods = false) - @Import(WebMvcAutoConfiguration.class) + @ImportAutoConfiguration({ MatchingAutoConfiguration.class, NonMatchingAutoConfiguration.class, + UnconditionalAutoConfiguration.class }) static class ErrorConfig { @Bean @@ -143,4 +146,26 @@ class ConditionEvaluationReportLoggingListenerTests { } + @AutoConfiguration + @ConditionalOnProperty(name = "com.example.property", matchIfMissing = true) + static class MatchingAutoConfiguration { + + } + + @AutoConfiguration + @ConditionalOnBean(Duration.class) + static class NonMatchingAutoConfiguration { + + } + + @AutoConfiguration + static class UnconditionalAutoConfiguration { + + @Bean + String example() { + return "example"; + } + + } + }