Add nullability annotations to tests in core/spring-boot-autoconfigure

See gh-47263
This commit is contained in:
Moritz Halbritter 2025-09-10 16:08:03 +02:00
parent b566b73be6
commit 57992512b7
29 changed files with 294 additions and 143 deletions

View File

@ -56,3 +56,7 @@ dependencies {
test { test {
jvmArgs += "--add-opens=java.base/java.net=ALL-UNNAMED" jvmArgs += "--add-opens=java.base/java.net=ALL-UNNAMED"
} }
tasks.named("compileTestJava") {
options.nullability.checking = "tests"
}

View File

@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -42,7 +43,7 @@ class AutoConfigurationExcludeFilterTests {
private static final Class<?> FILTERED = ExampleFilteredAutoConfiguration.class; private static final Class<?> FILTERED = ExampleFilteredAutoConfiguration.class;
private AnnotationConfigApplicationContext context; private @Nullable AnnotationConfigApplicationContext context;
@AfterEach @AfterEach
void cleanUp() { void cleanUp() {
@ -56,7 +57,10 @@ class AutoConfigurationExcludeFilterTests {
this.context = new AnnotationConfigApplicationContext(Config.class); this.context = new AnnotationConfigApplicationContext(Config.class);
assertThat(this.context.getBeansOfType(String.class)).hasSize(1); assertThat(this.context.getBeansOfType(String.class)).hasSize(1);
assertThat(this.context.getBean(String.class)).isEqualTo("test"); assertThat(this.context.getBean(String.class)).isEqualTo("test");
assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() -> this.context.getBean(FILTERED)); assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() -> {
assertThat(this.context).isNotNull();
this.context.getBean(FILTERED);
});
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)

View File

@ -28,6 +28,7 @@ import java.util.Set;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -83,39 +84,35 @@ class AutoConfigurationImportSelectorTests {
void importsAreSelectedWhenUsingEnableAutoConfiguration() { void importsAreSelectedWhenUsingEnableAutoConfiguration() {
String[] imports = selectImports(BasicEnableAutoConfiguration.class); String[] imports = selectImports(BasicEnableAutoConfiguration.class);
assertThat(imports).hasSameSizeAs(getAutoConfigurationClassNames()); assertThat(imports).hasSameSizeAs(getAutoConfigurationClassNames());
assertThat(this.importSelector.getLastEvent().getExclusions()).isEmpty(); assertThat(getLastEvent().getExclusions()).isEmpty();
} }
@Test @Test
void classExclusionsAreApplied() { void classExclusionsAreApplied() {
String[] imports = selectImports(EnableAutoConfigurationWithClassExclusions.class); String[] imports = selectImports(EnableAutoConfigurationWithClassExclusions.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1); assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1);
assertThat(this.importSelector.getLastEvent().getExclusions()) assertThat(getLastEvent().getExclusions()).contains(SeventhAutoConfiguration.class.getName());
.contains(SeventhAutoConfiguration.class.getName());
} }
@Test @Test
void classExclusionsAreAppliedWhenUsingSpringBootApplication() { void classExclusionsAreAppliedWhenUsingSpringBootApplication() {
String[] imports = selectImports(SpringBootApplicationWithClassExclusions.class); String[] imports = selectImports(SpringBootApplicationWithClassExclusions.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1); assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1);
assertThat(this.importSelector.getLastEvent().getExclusions()) assertThat(getLastEvent().getExclusions()).contains(SeventhAutoConfiguration.class.getName());
.contains(SeventhAutoConfiguration.class.getName());
} }
@Test @Test
void classNamesExclusionsAreApplied() { void classNamesExclusionsAreApplied() {
String[] imports = selectImports(EnableAutoConfigurationWithClassNameExclusions.class); String[] imports = selectImports(EnableAutoConfigurationWithClassNameExclusions.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1); assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1);
assertThat(this.importSelector.getLastEvent().getExclusions()) assertThat(getLastEvent().getExclusions()).contains("com.example.one.FirstAutoConfiguration");
.contains("com.example.one.FirstAutoConfiguration");
} }
@Test @Test
void classNamesExclusionsAreAppliedWhenUsingSpringBootApplication() { void classNamesExclusionsAreAppliedWhenUsingSpringBootApplication() {
String[] imports = selectImports(SpringBootApplicationWithClassNameExclusions.class); String[] imports = selectImports(SpringBootApplicationWithClassNameExclusions.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1); assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1);
assertThat(this.importSelector.getLastEvent().getExclusions()) assertThat(getLastEvent().getExclusions()).contains("com.example.three.ThirdAutoConfiguration");
.contains("com.example.three.ThirdAutoConfiguration");
} }
@Test @Test
@ -123,8 +120,7 @@ class AutoConfigurationImportSelectorTests {
this.environment.setProperty("spring.autoconfigure.exclude", "com.example.three.ThirdAutoConfiguration"); this.environment.setProperty("spring.autoconfigure.exclude", "com.example.three.ThirdAutoConfiguration");
String[] imports = selectImports(BasicEnableAutoConfiguration.class); String[] imports = selectImports(BasicEnableAutoConfiguration.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1); assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1);
assertThat(this.importSelector.getLastEvent().getExclusions()) assertThat(getLastEvent().getExclusions()).contains("com.example.three.ThirdAutoConfiguration");
.contains("com.example.three.ThirdAutoConfiguration");
} }
@Test @Test
@ -151,8 +147,8 @@ class AutoConfigurationImportSelectorTests {
private void testSeveralPropertyExclusionsAreApplied() { private void testSeveralPropertyExclusionsAreApplied() {
String[] imports = selectImports(BasicEnableAutoConfiguration.class); String[] imports = selectImports(BasicEnableAutoConfiguration.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 2); assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 2);
assertThat(this.importSelector.getLastEvent().getExclusions()) assertThat(getLastEvent().getExclusions()).contains("com.example.two.SecondAutoConfiguration",
.contains("com.example.two.SecondAutoConfiguration", "com.example.four.FourthAutoConfiguration"); "com.example.four.FourthAutoConfiguration");
} }
@Test @Test
@ -160,9 +156,8 @@ class AutoConfigurationImportSelectorTests {
this.environment.setProperty("spring.autoconfigure.exclude", "com.example.one.FirstAutoConfiguration"); this.environment.setProperty("spring.autoconfigure.exclude", "com.example.one.FirstAutoConfiguration");
String[] imports = selectImports(EnableAutoConfigurationWithClassAndClassNameExclusions.class); String[] imports = selectImports(EnableAutoConfigurationWithClassAndClassNameExclusions.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 3); assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 3);
assertThat(this.importSelector.getLastEvent().getExclusions()).contains( assertThat(getLastEvent().getExclusions()).contains("com.example.one.FirstAutoConfiguration",
"com.example.one.FirstAutoConfiguration", "com.example.five.FifthAutoConfiguration", "com.example.five.FifthAutoConfiguration", SeventhAutoConfiguration.class.getName());
SeventhAutoConfiguration.class.getName());
} }
@Test @Test
@ -202,7 +197,7 @@ class AutoConfigurationImportSelectorTests {
this.environment.setProperty("spring.autoconfigure.exclude", this.environment.setProperty("spring.autoconfigure.exclude",
"org.springframework.boot.autoconfigure.DoesNotExist2"); "org.springframework.boot.autoconfigure.DoesNotExist2");
selectImports(EnableAutoConfigurationWithAbsentClassNameExclude.class); selectImports(EnableAutoConfigurationWithAbsentClassNameExclude.class);
assertThat(this.importSelector.getLastEvent().getExclusions()).containsExactlyInAnyOrder( assertThat(getLastEvent().getExclusions()).containsExactlyInAnyOrder(
"org.springframework.boot.autoconfigure.DoesNotExist1", "org.springframework.boot.autoconfigure.DoesNotExist1",
"org.springframework.boot.autoconfigure.DoesNotExist2"); "org.springframework.boot.autoconfigure.DoesNotExist2");
} }
@ -269,11 +264,17 @@ class AutoConfigurationImportSelectorTests {
importSelector.setBeanClassLoader(Thread.currentThread().getContextClassLoader()); importSelector.setBeanClassLoader(Thread.currentThread().getContextClassLoader());
} }
private AutoConfigurationImportEvent getLastEvent() {
AutoConfigurationImportEvent result = this.importSelector.getLastEvent();
assertThat(result).isNotNull();
return result;
}
private final class TestAutoConfigurationImportSelector extends AutoConfigurationImportSelector { private final class TestAutoConfigurationImportSelector extends AutoConfigurationImportSelector {
private AutoConfigurationImportEvent lastEvent; private @Nullable AutoConfigurationImportEvent lastEvent;
TestAutoConfigurationImportSelector(Class<?> autoConfigurationAnnotation) { TestAutoConfigurationImportSelector(@Nullable Class<?> autoConfigurationAnnotation) {
super(autoConfigurationAnnotation); super(autoConfigurationAnnotation);
} }
@ -287,7 +288,7 @@ class AutoConfigurationImportSelectorTests {
return Collections.singletonList((event) -> this.lastEvent = event); return Collections.singletonList((event) -> this.lastEvent = event);
} }
AutoConfigurationImportEvent getLastEvent() { @Nullable AutoConfigurationImportEvent getLastEvent() {
return this.lastEvent; return this.lastEvent;
} }
@ -297,6 +298,7 @@ class AutoConfigurationImportSelectorTests {
private final Set<String> nonMatching = new HashSet<>(); private final Set<String> nonMatching = new HashSet<>();
@SuppressWarnings("NullAway.Init")
private BeanFactory beanFactory; private BeanFactory beanFactory;
TestAutoConfigurationImportFilter(String[] configurations, int... nonMatching) { TestAutoConfigurationImportFilter(String[] configurations, int... nonMatching) {
@ -306,7 +308,8 @@ class AutoConfigurationImportSelectorTests {
} }
@Override @Override
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) { public boolean[] match(@Nullable String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
boolean[] result = new boolean[autoConfigurationClasses.length]; boolean[] result = new boolean[autoConfigurationClasses.length];
for (int i = 0; i < result.length; i++) { for (int i = 0; i < result.length; i++) {
result[i] = !this.nonMatching.contains(autoConfigurationClasses[i]); result[i] = !this.nonMatching.contains(autoConfigurationClasses[i]);

View File

@ -26,6 +26,7 @@ import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -251,10 +252,14 @@ class AutoConfigurationSorterTests {
} }
private void addAutoConfigureAfter(Properties properties, String className, AnnotationMetadata annotationMetadata) { private void addAutoConfigureAfter(Properties properties, String className, AnnotationMetadata annotationMetadata) {
Map<String, Object> autoConfigureAfter = annotationMetadata Map<String, @Nullable Object> autoConfigureAfter = annotationMetadata
.getAnnotationAttributes(AutoConfigureAfter.class.getName(), true); .getAnnotationAttributes(AutoConfigureAfter.class.getName(), true);
if (autoConfigureAfter != null) { if (autoConfigureAfter != null) {
String value = merge((String[]) autoConfigureAfter.get("value"), (String[]) autoConfigureAfter.get("name")); String[] valueAttribute = (String[]) autoConfigureAfter.get("value");
String[] nameAttribute = (String[]) autoConfigureAfter.get("name");
assertThat(valueAttribute).isNotNull();
assertThat(nameAttribute).isNotNull();
String value = merge(valueAttribute, nameAttribute);
if (!value.isEmpty()) { if (!value.isEmpty()) {
properties.put(className + ".AutoConfigureAfter", value); properties.put(className + ".AutoConfigureAfter", value);
} }
@ -263,11 +268,14 @@ class AutoConfigurationSorterTests {
private void addAutoConfigureBefore(Properties properties, String className, private void addAutoConfigureBefore(Properties properties, String className,
AnnotationMetadata annotationMetadata) { AnnotationMetadata annotationMetadata) {
Map<String, Object> autoConfigureBefore = annotationMetadata Map<String, @Nullable Object> autoConfigureBefore = annotationMetadata
.getAnnotationAttributes(AutoConfigureBefore.class.getName(), true); .getAnnotationAttributes(AutoConfigureBefore.class.getName(), true);
if (autoConfigureBefore != null) { if (autoConfigureBefore != null) {
String value = merge((String[]) autoConfigureBefore.get("value"), String[] valueAttribute = (String[]) autoConfigureBefore.get("value");
(String[]) autoConfigureBefore.get("name")); String[] nameAttribute = (String[]) autoConfigureBefore.get("name");
assertThat(valueAttribute).isNotNull();
assertThat(nameAttribute).isNotNull();
String value = merge(valueAttribute, nameAttribute);
if (!value.isEmpty()) { if (!value.isEmpty()) {
properties.put(className + ".AutoConfigureBefore", value); properties.put(className + ".AutoConfigureBefore", value);
} }
@ -275,7 +283,7 @@ class AutoConfigurationSorterTests {
} }
private void addAutoConfigureOrder(Properties properties, String className, AnnotationMetadata annotationMetadata) { private void addAutoConfigureOrder(Properties properties, String className, AnnotationMetadata annotationMetadata) {
Map<String, Object> autoConfigureOrder = annotationMetadata Map<String, @Nullable Object> autoConfigureOrder = annotationMetadata
.getAnnotationAttributes(AutoConfigureOrder.class.getName()); .getAnnotationAttributes(AutoConfigureOrder.class.getName());
if (autoConfigureOrder != null) { if (autoConfigureOrder != null) {
Integer order = (Integer) autoConfigureOrder.get("order"); Integer order = (Integer) autoConfigureOrder.get("order");

View File

@ -16,11 +16,13 @@
package org.springframework.boot.autoconfigure; package org.springframework.boot.autoconfigure;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
public class EarlyInitFactoryBean implements FactoryBean<String> { public class EarlyInitFactoryBean implements FactoryBean<String> {
private String propertyFromConfig; private @Nullable String propertyFromConfig;
public void setPropertyFromConfig(String propertyFromConfig) { public void setPropertyFromConfig(String propertyFromConfig) {
this.propertyFromConfig = propertyFromConfig; this.propertyFromConfig = propertyFromConfig;
@ -32,12 +34,12 @@ public class EarlyInitFactoryBean implements FactoryBean<String> {
} }
@Override @Override
public Class<?> getObjectType() { public @Nullable Class<?> getObjectType() {
return null; return null;
} }
@Override @Override
public String getObject() throws Exception { public @Nullable String getObject() throws Exception {
return this.propertyFromConfig; return this.propertyFromConfig;
} }

View File

@ -57,6 +57,7 @@ class SharedMetadataReaderFactoryContextInitializerTests {
.getField(application, "initializers"); .getField(application, "initializers");
// Simulate what would happen if an initializer was added using spring.factories // Simulate what would happen if an initializer was added using spring.factories
// and happened to be loaded first // and happened to be loaded first
assertThat(initializers).isNotNull();
initializers.add(0, new Initializer()); initializers.add(0, new Initializer());
GenericApplicationContext context = (GenericApplicationContext) application.run(); GenericApplicationContext context = (GenericApplicationContext) application.run();
BeanDefinition definition = context.getBeanDefinition(SharedMetadataReaderFactoryContextInitializer.BEAN_NAME); BeanDefinition definition = context.getBeanDefinition(SharedMetadataReaderFactoryContextInitializer.BEAN_NAME);

View File

@ -44,7 +44,9 @@ class AbstractNestedConditionTests {
void invalidMemberPhase() { void invalidMemberPhase() {
this.contextRunner.withUserConfiguration(InvalidConfig.class).run((context) -> { this.contextRunner.withUserConfiguration(InvalidConfig.class).run((context) -> {
assertThat(context).hasFailed(); assertThat(context).hasFailed();
assertThat(context.getStartupFailure().getCause()).isInstanceOf(IllegalStateException.class) Throwable startupFailure = context.getStartupFailure();
assertThat(startupFailure).isNotNull();
assertThat(startupFailure.getCause()).isInstanceOf(IllegalStateException.class)
.hasMessageContaining("Nested condition " + InvalidNestedCondition.class.getName() .hasMessageContaining("Nested condition " + InvalidNestedCondition.class.getName()
+ " uses a configuration phase that is inappropriate for class " + " uses a configuration phase that is inappropriate for class "
+ OnBeanCondition.class.getName()); + OnBeanCondition.class.getName());
@ -55,7 +57,9 @@ class AbstractNestedConditionTests {
void invalidNestedMemberPhase() { void invalidNestedMemberPhase() {
this.contextRunner.withUserConfiguration(DoubleNestedConfig.class).run((context) -> { this.contextRunner.withUserConfiguration(DoubleNestedConfig.class).run((context) -> {
assertThat(context).hasFailed(); assertThat(context).hasFailed();
assertThat(context.getStartupFailure().getCause()).isInstanceOf(IllegalStateException.class) Throwable startupFailure = context.getStartupFailure();
assertThat(startupFailure).isNotNull();
assertThat(startupFailure.getCause()).isInstanceOf(IllegalStateException.class)
.hasMessageContaining("Nested condition " + DoubleNestedCondition.class.getName() .hasMessageContaining("Nested condition " + DoubleNestedCondition.class.getName()
+ " uses a configuration phase that is inappropriate for class " + " uses a configuration phase that is inappropriate for class "
+ ValidNestedCondition.class.getName()); + ValidNestedCondition.class.getName());

View File

@ -20,12 +20,14 @@ import java.time.Duration;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration;
@ -61,19 +63,22 @@ class ConditionEvaluationReportTests {
private ConditionEvaluationReport report; private ConditionEvaluationReport report;
@Mock @Mock
@SuppressWarnings("NullAway.Init")
private Condition condition1; private Condition condition1;
@Mock @Mock
@SuppressWarnings("NullAway.Init")
private Condition condition2; private Condition condition2;
@Mock @Mock
@SuppressWarnings("NullAway.Init")
private Condition condition3; private Condition condition3;
private ConditionOutcome outcome1; private @Nullable ConditionOutcome outcome1;
private ConditionOutcome outcome2; private @Nullable ConditionOutcome outcome2;
private ConditionOutcome outcome3; private @Nullable ConditionOutcome outcome3;
@BeforeEach @BeforeEach
void setup() { void setup() {
@ -90,21 +95,25 @@ class ConditionEvaluationReportTests {
@Test @Test
void parent() { void parent() {
this.beanFactory.setParentBeanFactory(new DefaultListableBeanFactory()); this.beanFactory.setParentBeanFactory(new DefaultListableBeanFactory());
ConditionEvaluationReport.get((ConfigurableListableBeanFactory) this.beanFactory.getParentBeanFactory()); BeanFactory parentBeanFactory = this.beanFactory.getParentBeanFactory();
assertThat(parentBeanFactory).isNotNull();
ConditionEvaluationReport.get((ConfigurableListableBeanFactory) parentBeanFactory);
assertThat(this.report).isSameAs(ConditionEvaluationReport.get(this.beanFactory)); assertThat(this.report).isSameAs(ConditionEvaluationReport.get(this.beanFactory));
assertThat(this.report).isNotNull(); assertThat(this.report).isNotNull();
assertThat(this.report.getParent()).isNotNull(); assertThat(this.report.getParent()).isNotNull();
ConditionEvaluationReport.get((ConfigurableListableBeanFactory) this.beanFactory.getParentBeanFactory()); ConditionEvaluationReport.get((ConfigurableListableBeanFactory) parentBeanFactory);
assertThat(this.report).isSameAs(ConditionEvaluationReport.get(this.beanFactory)); assertThat(this.report).isSameAs(ConditionEvaluationReport.get(this.beanFactory));
assertThat(this.report.getParent()).isSameAs(ConditionEvaluationReport assertThat(this.report.getParent())
.get((ConfigurableListableBeanFactory) this.beanFactory.getParentBeanFactory())); .isSameAs(ConditionEvaluationReport.get((ConfigurableListableBeanFactory) parentBeanFactory));
} }
@Test @Test
void parentBottomUp() { void parentBottomUp() {
this.beanFactory = new DefaultListableBeanFactory(); // NB: overrides setup this.beanFactory = new DefaultListableBeanFactory(); // NB: overrides setup
this.beanFactory.setParentBeanFactory(new DefaultListableBeanFactory()); this.beanFactory.setParentBeanFactory(new DefaultListableBeanFactory());
ConditionEvaluationReport.get((ConfigurableListableBeanFactory) this.beanFactory.getParentBeanFactory()); BeanFactory parentBeanFactory = this.beanFactory.getParentBeanFactory();
assertThat(parentBeanFactory).isNotNull();
ConditionEvaluationReport.get((ConfigurableListableBeanFactory) parentBeanFactory);
this.report = ConditionEvaluationReport.get(this.beanFactory); this.report = ConditionEvaluationReport.get(this.beanFactory);
assertThat(this.report).isNotNull(); assertThat(this.report).isNotNull();
assertThat(this.report).isNotSameAs(this.report.getParent()); assertThat(this.report).isNotSameAs(this.report.getParent());
@ -122,7 +131,9 @@ class ConditionEvaluationReportTests {
this.report.recordConditionEvaluation("b", this.condition3, this.outcome3); this.report.recordConditionEvaluation("b", this.condition3, this.outcome3);
Map<String, ConditionAndOutcomes> map = this.report.getConditionAndOutcomesBySource(); Map<String, ConditionAndOutcomes> map = this.report.getConditionAndOutcomesBySource();
assertThat(map).hasSize(2); assertThat(map).hasSize(2);
Iterator<ConditionAndOutcome> iterator = map.get("a").iterator(); ConditionAndOutcomes a = map.get("a");
assertThat(a).isNotNull();
Iterator<ConditionAndOutcome> iterator = a.iterator();
ConditionAndOutcome conditionAndOutcome = iterator.next(); ConditionAndOutcome conditionAndOutcome = iterator.next();
assertThat(conditionAndOutcome.getCondition()).isEqualTo(this.condition1); assertThat(conditionAndOutcome.getCondition()).isEqualTo(this.condition1);
assertThat(conditionAndOutcome.getOutcome()).isEqualTo(this.outcome1); assertThat(conditionAndOutcome.getOutcome()).isEqualTo(this.outcome1);
@ -130,7 +141,9 @@ class ConditionEvaluationReportTests {
assertThat(conditionAndOutcome.getCondition()).isEqualTo(this.condition2); assertThat(conditionAndOutcome.getCondition()).isEqualTo(this.condition2);
assertThat(conditionAndOutcome.getOutcome()).isEqualTo(this.outcome2); assertThat(conditionAndOutcome.getOutcome()).isEqualTo(this.outcome2);
assertThat(iterator.hasNext()).isFalse(); assertThat(iterator.hasNext()).isFalse();
iterator = map.get("b").iterator(); ConditionAndOutcomes b = map.get("b");
assertThat(b).isNotNull();
iterator = b.iterator();
conditionAndOutcome = iterator.next(); conditionAndOutcome = iterator.next();
assertThat(conditionAndOutcome.getCondition()).isEqualTo(this.condition3); assertThat(conditionAndOutcome.getCondition()).isEqualTo(this.condition3);
assertThat(conditionAndOutcome.getOutcome()).isEqualTo(this.outcome3); assertThat(conditionAndOutcome.getOutcome()).isEqualTo(this.outcome3);
@ -140,13 +153,17 @@ class ConditionEvaluationReportTests {
@Test @Test
void fullMatch() { void fullMatch() {
prepareMatches(true, true, true); prepareMatches(true, true, true);
assertThat(this.report.getConditionAndOutcomesBySource().get("a").isFullMatch()).isTrue(); ConditionAndOutcomes a = this.report.getConditionAndOutcomesBySource().get("a");
assertThat(a).isNotNull();
assertThat(a.isFullMatch()).isTrue();
} }
@Test @Test
void notFullMatch() { void notFullMatch() {
prepareMatches(true, false, true); prepareMatches(true, false, true);
assertThat(this.report.getConditionAndOutcomesBySource().get("a").isFullMatch()).isFalse(); ConditionAndOutcomes a = this.report.getConditionAndOutcomesBySource().get("a");
assertThat(a).isNotNull();
assertThat(a.isFullMatch()).isFalse();
} }
private void prepareMatches(boolean m1, boolean m2, boolean m3) { private void prepareMatches(boolean m1, boolean m2, boolean m3) {
@ -203,9 +220,13 @@ class ConditionEvaluationReportTests {
Map<String, ConditionAndOutcomes> sourceOutcomes = report.getConditionAndOutcomesBySource(); Map<String, ConditionAndOutcomes> sourceOutcomes = report.getConditionAndOutcomesBySource();
assertThat(context.containsBean("negativeOuterPositiveInnerBean")).isFalse(); assertThat(context.containsBean("negativeOuterPositiveInnerBean")).isFalse();
String negativeConfig = NegativeOuterConfig.class.getName(); String negativeConfig = NegativeOuterConfig.class.getName();
assertThat(sourceOutcomes.get(negativeConfig).isFullMatch()).isFalse(); ConditionAndOutcomes negativeOutcome = sourceOutcomes.get(negativeConfig);
assertThat(negativeOutcome).isNotNull();
assertThat(negativeOutcome.isFullMatch()).isFalse();
String positiveConfig = NegativeOuterConfig.PositiveInnerConfig.class.getName(); String positiveConfig = NegativeOuterConfig.PositiveInnerConfig.class.getName();
assertThat(sourceOutcomes.get(positiveConfig).isFullMatch()).isFalse(); ConditionAndOutcomes positiveOutcome = sourceOutcomes.get(positiveConfig);
assertThat(positiveOutcome).isNotNull();
assertThat(positiveOutcome.isFullMatch()).isFalse();
} }
@Test @Test

View File

@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.condition;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -42,7 +43,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
*/ */
class ConditionalOnBooleanPropertyTests { class ConditionalOnBooleanPropertyTests {
private ConfigurableApplicationContext context; private @Nullable ConfigurableApplicationContext context;
private final ConfigurableEnvironment environment = new StandardEnvironment(); private final ConfigurableEnvironment environment = new StandardEnvironment();
@ -56,97 +57,97 @@ class ConditionalOnBooleanPropertyTests {
@Test @Test
void defaultsWhenTrue() { void defaultsWhenTrue() {
load(Defaults.class, "test=true"); load(Defaults.class, "test=true");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void defaultsWhenFalse() { void defaultsWhenFalse() {
load(Defaults.class, "test=false"); load(Defaults.class, "test=false");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void defaultsWhenMissing() { void defaultsWhenMissing() {
load(Defaults.class); load(Defaults.class);
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void havingValueTrueMatchIfMissingFalseWhenTrue() { void havingValueTrueMatchIfMissingFalseWhenTrue() {
load(HavingValueTrueMatchIfMissingFalse.class, "test=true"); load(HavingValueTrueMatchIfMissingFalse.class, "test=true");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void havingValueTrueMatchIfMissingFalseWhenFalse() { void havingValueTrueMatchIfMissingFalseWhenFalse() {
load(HavingValueTrueMatchIfMissingFalse.class, "test=false"); load(HavingValueTrueMatchIfMissingFalse.class, "test=false");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void havingValueTrueMatchIfMissingFalseWhenMissing() { void havingValueTrueMatchIfMissingFalseWhenMissing() {
load(HavingValueTrueMatchIfMissingFalse.class); load(HavingValueTrueMatchIfMissingFalse.class);
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void havingValueTrueMatchIfMissingTrueWhenTrue() { void havingValueTrueMatchIfMissingTrueWhenTrue() {
load(HavingValueTrueMatchIfMissingTrue.class, "test=true"); load(HavingValueTrueMatchIfMissingTrue.class, "test=true");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void havingValueTrueMatchIfMissingTrueWhenFalse() { void havingValueTrueMatchIfMissingTrueWhenFalse() {
load(HavingValueTrueMatchIfMissingTrue.class, "test=false"); load(HavingValueTrueMatchIfMissingTrue.class, "test=false");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void havingValueTrueMatchIfMissingTrueWhenMissing() { void havingValueTrueMatchIfMissingTrueWhenMissing() {
load(HavingValueTrueMatchIfMissingTrue.class); load(HavingValueTrueMatchIfMissingTrue.class);
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void havingValueFalseMatchIfMissingFalseWhenTrue() { void havingValueFalseMatchIfMissingFalseWhenTrue() {
load(HavingValueFalseMatchIfMissingFalse.class, "test=true"); load(HavingValueFalseMatchIfMissingFalse.class, "test=true");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void havingValueFalseMatchIfMissingFalseWhenFalse() { void havingValueFalseMatchIfMissingFalseWhenFalse() {
load(HavingValueFalseMatchIfMissingFalse.class, "test=false"); load(HavingValueFalseMatchIfMissingFalse.class, "test=false");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void havingValueFalseMatchIfMissingFalseWhenMissing() { void havingValueFalseMatchIfMissingFalseWhenMissing() {
load(HavingValueFalseMatchIfMissingFalse.class); load(HavingValueFalseMatchIfMissingFalse.class);
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void havingValueFalseMatchIfMissingTrueWhenTrue() { void havingValueFalseMatchIfMissingTrueWhenTrue() {
load(HavingValueFalseMatchIfMissingTrue.class, "test=true"); load(HavingValueFalseMatchIfMissingTrue.class, "test=true");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void havingValueFalseMatchIfMissingTrueWhenFalse() { void havingValueFalseMatchIfMissingTrueWhenFalse() {
load(HavingValueFalseMatchIfMissingTrue.class, "test=false"); load(HavingValueFalseMatchIfMissingTrue.class, "test=false");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void havingValueFalseMatchIfMissingTrueWhenMissing() { void havingValueFalseMatchIfMissingTrueWhenMissing() {
load(HavingValueFalseMatchIfMissingTrue.class); load(HavingValueFalseMatchIfMissingTrue.class);
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void withPrefix() { void withPrefix() {
load(HavingValueFalseMatchIfMissingTrue.class, "foo.test=true"); load(HavingValueFalseMatchIfMissingTrue.class, "foo.test=true");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
@ -166,14 +167,14 @@ class ConditionalOnBooleanPropertyTests {
@Test @Test
void conditionReportWhenMatched() { void conditionReportWhenMatched() {
load(Defaults.class, "test=true"); load(Defaults.class, "test=true");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
assertThat(getConditionEvaluationReport()).contains("@ConditionalOnBooleanProperty (test=true) matched"); assertThat(getConditionEvaluationReport()).contains("@ConditionalOnBooleanProperty (test=true) matched");
} }
@Test @Test
void conditionReportWhenDoesNotMatch() { void conditionReportWhenDoesNotMatch() {
load(Defaults.class, "test=false"); load(Defaults.class, "test=false");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
assertThat(getConditionEvaluationReport()) assertThat(getConditionEvaluationReport())
.contains("@ConditionalOnBooleanProperty (test=true) found different value in property 'test'"); .contains("@ConditionalOnBooleanProperty (test=true) found different value in property 'test'");
} }
@ -181,7 +182,7 @@ class ConditionalOnBooleanPropertyTests {
@Test @Test
void repeatablePropertiesConditionReportWhenMatched() { void repeatablePropertiesConditionReportWhenMatched() {
load(RepeatablePropertiesRequiredConfiguration.class, "property1=true", "property2=true"); load(RepeatablePropertiesRequiredConfiguration.class, "property1=true", "property2=true");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
String report = getConditionEvaluationReport(); String report = getConditionEvaluationReport();
assertThat(report).contains("@ConditionalOnBooleanProperty (property1=true) matched"); assertThat(report).contains("@ConditionalOnBooleanProperty (property1=true) matched");
assertThat(report).contains("@ConditionalOnBooleanProperty (property2=true) matched"); assertThat(report).contains("@ConditionalOnBooleanProperty (property2=true) matched");
@ -199,6 +200,7 @@ class ConditionalOnBooleanPropertyTests {
} }
private String getConditionEvaluationReport() { private String getConditionEvaluationReport() {
assertThat(this.context).isNotNull();
return ConditionEvaluationReport.get(this.context.getBeanFactory()) return ConditionEvaluationReport.get(this.context.getBeanFactory())
.getConditionAndOutcomesBySource() .getConditionAndOutcomesBySource()
.values() .values()
@ -215,6 +217,11 @@ class ConditionalOnBooleanPropertyTests {
.run(); .run();
} }
private boolean containsBean() {
assertThat(this.context).isNotNull();
return this.context.containsBean("foo");
}
abstract static class BeanConfiguration { abstract static class BeanConfiguration {
@Bean @Bean

View File

@ -105,8 +105,10 @@ class ConditionalOnJavaTests {
FilteredClassLoader classLoader = new FilteredClassLoader(hiddenClasses); FilteredClassLoader classLoader = new FilteredClassLoader(hiddenClasses);
Class<?> javaVersionClass = Class.forName(JavaVersion.class.getName(), false, classLoader); Class<?> javaVersionClass = Class.forName(JavaVersion.class.getName(), false, classLoader);
Method getJavaVersionMethod = ReflectionUtils.findMethod(javaVersionClass, "getJavaVersion"); Method getJavaVersionMethod = ReflectionUtils.findMethod(javaVersionClass, "getJavaVersion");
assertThat(getJavaVersionMethod).isNotNull();
Object javaVersion = ReflectionUtils.invokeMethod(getJavaVersionMethod, null); Object javaVersion = ReflectionUtils.invokeMethod(getJavaVersionMethod, null);
classLoader.close(); classLoader.close();
assertThat(javaVersion).isNotNull();
return javaVersion.toString(); return javaVersion.toString();
} }

View File

@ -21,6 +21,7 @@ import java.util.Map;
import javax.naming.Context; import javax.naming.Context;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -29,6 +30,7 @@ import org.springframework.boot.autoconfigure.jndi.JndiPropertiesHidingClassLoad
import org.springframework.boot.autoconfigure.jndi.TestableInitialContextFactory; import org.springframework.boot.autoconfigure.jndi.TestableInitialContextFactory;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.core.type.AnnotatedTypeMetadata;
@ -47,7 +49,7 @@ class ConditionalOnJndiTests {
private ClassLoader threadContextClassLoader; private ClassLoader threadContextClassLoader;
private String initialContextFactory; private @Nullable String initialContextFactory;
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();
@ -101,14 +103,16 @@ class ConditionalOnJndiTests {
@Test @Test
void jndiLocationNotFound() { void jndiLocationNotFound() {
ConditionOutcome outcome = this.condition.getMatchOutcome(null, mockMetadata("java:/a")); ConditionOutcome outcome = this.condition.getMatchOutcome(mock(ConditionContext.class),
mockMetadata("java:/a"));
assertThat(outcome.isMatch()).isFalse(); assertThat(outcome.isMatch()).isFalse();
} }
@Test @Test
void jndiLocationFound() { void jndiLocationFound() {
this.condition.setFoundLocation("java:/b"); this.condition.setFoundLocation("java:/b");
ConditionOutcome outcome = this.condition.getMatchOutcome(null, mockMetadata("java:/a", "java:/b")); ConditionOutcome outcome = this.condition.getMatchOutcome(mock(ConditionContext.class),
mockMetadata("java:/a", "java:/b"));
assertThat(outcome.isMatch()).isTrue(); assertThat(outcome.isMatch()).isTrue();
} }
@ -151,7 +155,7 @@ class ConditionalOnJndiTests {
private final boolean jndiAvailable = true; private final boolean jndiAvailable = true;
private String foundLocation; private @Nullable String foundLocation;
@Override @Override
protected boolean isJndiAvailable() { protected boolean isJndiAvailable() {
@ -162,7 +166,7 @@ class ConditionalOnJndiTests {
protected JndiLocator getJndiLocator(String[] locations) { protected JndiLocator getJndiLocator(String[] locations) {
return new JndiLocator(locations) { return new JndiLocator(locations) {
@Override @Override
public String lookupFirstLocation() { public @Nullable String lookupFirstLocation() {
return MockableOnJndi.this.foundLocation; return MockableOnJndi.this.foundLocation;
} }
}; };

View File

@ -23,6 +23,7 @@ import java.lang.annotation.Target;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -50,7 +51,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
*/ */
class ConditionalOnPropertyTests { class ConditionalOnPropertyTests {
private ConfigurableApplicationContext context; private @Nullable ConfigurableApplicationContext context;
private final ConfigurableEnvironment environment = new StandardEnvironment(); private final ConfigurableEnvironment environment = new StandardEnvironment();
@ -64,135 +65,140 @@ class ConditionalOnPropertyTests {
@Test @Test
void allPropertiesAreDefined() { void allPropertiesAreDefined() {
load(MultiplePropertiesRequiredConfiguration.class, "property1=value1", "property2=value2"); load(MultiplePropertiesRequiredConfiguration.class, "property1=value1", "property2=value2");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void notAllPropertiesAreDefined() { void notAllPropertiesAreDefined() {
load(MultiplePropertiesRequiredConfiguration.class, "property1=value1"); load(MultiplePropertiesRequiredConfiguration.class, "property1=value1");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void propertyValueEqualsFalse() { void propertyValueEqualsFalse() {
load(MultiplePropertiesRequiredConfiguration.class, "property1=false", "property2=value2"); load(MultiplePropertiesRequiredConfiguration.class, "property1=false", "property2=value2");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void propertyValueEqualsFALSE() { void propertyValueEqualsFALSE() {
load(MultiplePropertiesRequiredConfiguration.class, "property1=FALSE", "property2=value2"); load(MultiplePropertiesRequiredConfiguration.class, "property1=FALSE", "property2=value2");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void relaxedName() { void relaxedName() {
load(RelaxedPropertiesRequiredConfiguration.class, "spring.theRelaxedProperty=value1"); load(RelaxedPropertiesRequiredConfiguration.class, "spring.theRelaxedProperty=value1");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void prefixWithoutPeriod() { void prefixWithoutPeriod() {
load(RelaxedPropertiesRequiredConfigurationWithShortPrefix.class, "spring.property=value1"); load(RelaxedPropertiesRequiredConfigurationWithShortPrefix.class, "spring.property=value1");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
// Enabled by default // Enabled by default
void enabledIfNotConfiguredOtherwise() { void enabledIfNotConfiguredOtherwise() {
load(EnabledIfNotConfiguredOtherwiseConfig.class); load(EnabledIfNotConfiguredOtherwiseConfig.class);
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void enabledIfNotConfiguredOtherwiseWithConfig() { void enabledIfNotConfiguredOtherwiseWithConfig() {
load(EnabledIfNotConfiguredOtherwiseConfig.class, "simple.myProperty:false"); load(EnabledIfNotConfiguredOtherwiseConfig.class, "simple.myProperty:false");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void enabledIfNotConfiguredOtherwiseWithConfigDifferentCase() { void enabledIfNotConfiguredOtherwiseWithConfigDifferentCase() {
load(EnabledIfNotConfiguredOtherwiseConfig.class, "simple.my-property:FALSE"); load(EnabledIfNotConfiguredOtherwiseConfig.class, "simple.my-property:FALSE");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
// Disabled by default // Disabled by default
void disableIfNotConfiguredOtherwise() { void disableIfNotConfiguredOtherwise() {
load(DisabledIfNotConfiguredOtherwiseConfig.class); load(DisabledIfNotConfiguredOtherwiseConfig.class);
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void disableIfNotConfiguredOtherwiseWithConfig() { void disableIfNotConfiguredOtherwiseWithConfig() {
load(DisabledIfNotConfiguredOtherwiseConfig.class, "simple.myProperty:true"); load(DisabledIfNotConfiguredOtherwiseConfig.class, "simple.myProperty:true");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void disableIfNotConfiguredOtherwiseWithConfigDifferentCase() { void disableIfNotConfiguredOtherwiseWithConfigDifferentCase() {
load(DisabledIfNotConfiguredOtherwiseConfig.class, "simple.myproperty:TrUe"); load(DisabledIfNotConfiguredOtherwiseConfig.class, "simple.myproperty:TrUe");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void simpleValueIsSet() { void simpleValueIsSet() {
load(SimpleValueConfig.class, "simple.myProperty:bar"); load(SimpleValueConfig.class, "simple.myProperty:bar");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void caseInsensitive() { void caseInsensitive() {
load(SimpleValueConfig.class, "simple.myProperty:BaR"); load(SimpleValueConfig.class, "simple.myProperty:BaR");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void defaultValueIsSet() { void defaultValueIsSet() {
load(DefaultValueConfig.class, "simple.myProperty:bar"); load(DefaultValueConfig.class, "simple.myProperty:bar");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void defaultValueIsNotSet() { void defaultValueIsNotSet() {
load(DefaultValueConfig.class); load(DefaultValueConfig.class);
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void defaultValueIsSetDifferentValue() { void defaultValueIsSetDifferentValue() {
load(DefaultValueConfig.class, "simple.myProperty:another"); load(DefaultValueConfig.class, "simple.myProperty:another");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void prefix() { void prefix() {
load(PrefixValueConfig.class, "simple.myProperty:bar"); load(PrefixValueConfig.class, "simple.myProperty:bar");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void relaxedEnabledByDefault() { void relaxedEnabledByDefault() {
load(PrefixValueConfig.class, "simple.myProperty:bar"); load(PrefixValueConfig.class, "simple.myProperty:bar");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void multiValuesAllSet() { void multiValuesAllSet() {
load(MultiValuesConfig.class, "simple.my-property:bar", "simple.my-another-property:bar"); load(MultiValuesConfig.class, "simple.my-property:bar", "simple.my-another-property:bar");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void multiValuesOnlyOneSet() { void multiValuesOnlyOneSet() {
load(MultiValuesConfig.class, "simple.my-property:bar"); load(MultiValuesConfig.class, "simple.my-property:bar");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void usingValueAttribute() { void usingValueAttribute() {
load(ValueAttribute.class, "some.property"); load(ValueAttribute.class, "some.property");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
}
private boolean containsBean() {
assertThat(this.context).isNotNull();
return this.context.containsBean("foo");
} }
@Test @Test
@ -215,68 +221,68 @@ class ConditionalOnPropertyTests {
@Test @Test
void metaAnnotationConditionMatchesWhenPropertyIsSet() { void metaAnnotationConditionMatchesWhenPropertyIsSet() {
load(MetaAnnotation.class, "my.feature.enabled=true"); load(MetaAnnotation.class, "my.feature.enabled=true");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void metaAnnotationConditionDoesNotMatchWhenPropertyIsNotSet() { void metaAnnotationConditionDoesNotMatchWhenPropertyIsNotSet() {
load(MetaAnnotation.class); load(MetaAnnotation.class);
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void metaAndDirectAnnotationConditionDoesNotMatchWhenOnlyDirectPropertyIsSet() { void metaAndDirectAnnotationConditionDoesNotMatchWhenOnlyDirectPropertyIsSet() {
load(MetaAnnotationAndDirectAnnotation.class, "my.other.feature.enabled=true"); load(MetaAnnotationAndDirectAnnotation.class, "my.other.feature.enabled=true");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void metaAndDirectAnnotationConditionDoesNotMatchWhenOnlyMetaPropertyIsSet() { void metaAndDirectAnnotationConditionDoesNotMatchWhenOnlyMetaPropertyIsSet() {
load(MetaAnnotationAndDirectAnnotation.class, "my.feature.enabled=true"); load(MetaAnnotationAndDirectAnnotation.class, "my.feature.enabled=true");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void metaAndDirectAnnotationConditionDoesNotMatchWhenNeitherPropertyIsSet() { void metaAndDirectAnnotationConditionDoesNotMatchWhenNeitherPropertyIsSet() {
load(MetaAnnotationAndDirectAnnotation.class); load(MetaAnnotationAndDirectAnnotation.class);
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void metaAndDirectAnnotationConditionMatchesWhenBothPropertiesAreSet() { void metaAndDirectAnnotationConditionMatchesWhenBothPropertiesAreSet() {
load(MetaAnnotationAndDirectAnnotation.class, "my.feature.enabled=true", "my.other.feature.enabled=true"); load(MetaAnnotationAndDirectAnnotation.class, "my.feature.enabled=true", "my.other.feature.enabled=true");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void metaAnnotationWithAliasConditionMatchesWhenPropertyIsSet() { void metaAnnotationWithAliasConditionMatchesWhenPropertyIsSet() {
load(MetaAnnotationWithAlias.class, "my.feature.enabled=true"); load(MetaAnnotationWithAlias.class, "my.feature.enabled=true");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void metaAndDirectAnnotationWithAliasConditionDoesNotMatchWhenOnlyMetaPropertyIsSet() { void metaAndDirectAnnotationWithAliasConditionDoesNotMatchWhenOnlyMetaPropertyIsSet() {
load(MetaAnnotationAndDirectAnnotationWithAlias.class, "my.feature.enabled=true"); load(MetaAnnotationAndDirectAnnotationWithAlias.class, "my.feature.enabled=true");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void metaAndDirectAnnotationWithAliasConditionDoesNotMatchWhenOnlyDirectPropertyIsSet() { void metaAndDirectAnnotationWithAliasConditionDoesNotMatchWhenOnlyDirectPropertyIsSet() {
load(MetaAnnotationAndDirectAnnotationWithAlias.class, "my.other.feature.enabled=true"); load(MetaAnnotationAndDirectAnnotationWithAlias.class, "my.other.feature.enabled=true");
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(containsBean()).isFalse();
} }
@Test @Test
void metaAndDirectAnnotationWithAliasConditionMatchesWhenBothPropertiesAreSet() { void metaAndDirectAnnotationWithAliasConditionMatchesWhenBothPropertiesAreSet() {
load(MetaAnnotationAndDirectAnnotationWithAlias.class, "my.feature.enabled=true", load(MetaAnnotationAndDirectAnnotationWithAlias.class, "my.feature.enabled=true",
"my.other.feature.enabled=true"); "my.other.feature.enabled=true");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
} }
@Test @Test
void multiplePropertiesConditionReportWhenMatched() { void multiplePropertiesConditionReportWhenMatched() {
load(MultiplePropertiesRequiredConfiguration.class, "property1=value1", "property2=value2"); load(MultiplePropertiesRequiredConfiguration.class, "property1=value1", "property2=value2");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
assertThat(getConditionEvaluationReport()).contains("@ConditionalOnProperty ([property1,property2]) matched"); assertThat(getConditionEvaluationReport()).contains("@ConditionalOnProperty ([property1,property2]) matched");
} }
@ -290,7 +296,7 @@ class ConditionalOnPropertyTests {
@Test @Test
void repeatablePropertiesConditionReportWhenMatched() { void repeatablePropertiesConditionReportWhenMatched() {
load(RepeatablePropertiesRequiredConfiguration.class, "property1=value1", "property2=value2"); load(RepeatablePropertiesRequiredConfiguration.class, "property1=value1", "property2=value2");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(containsBean()).isTrue();
String report = getConditionEvaluationReport(); String report = getConditionEvaluationReport();
assertThat(report).contains("@ConditionalOnProperty (property1) matched"); assertThat(report).contains("@ConditionalOnProperty (property1) matched");
assertThat(report).contains("@ConditionalOnProperty (property2) matched"); assertThat(report).contains("@ConditionalOnProperty (property2) matched");
@ -311,6 +317,7 @@ class ConditionalOnPropertyTests {
} }
private String getConditionEvaluationReport() { private String getConditionEvaluationReport() {
assertThat(this.context).isNotNull();
return ConditionEvaluationReport.get(this.context.getBeanFactory()) return ConditionEvaluationReport.get(this.context.getBeanFactory())
.getConditionAndOutcomesBySource() .getConditionAndOutcomesBySource()
.values() .values()

View File

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.condition; package org.springframework.boot.autoconfigure.condition;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -39,7 +40,7 @@ import static org.assertj.core.api.Assertions.entry;
*/ */
class ConditionalOnWebApplicationTests { class ConditionalOnWebApplicationTests {
private ConfigurableApplicationContext context; private @Nullable ConfigurableApplicationContext context;
@AfterEach @AfterEach
void closeContext() { void closeContext() {

View File

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.condition; package org.springframework.boot.autoconfigure.condition;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.ObjectMapper;
@ -45,6 +46,7 @@ class OnBeanConditionTypeDeductionFailureTests {
.isThrownBy(() -> new AnnotationConfigApplicationContext(ImportingConfiguration.class).close()) .isThrownBy(() -> new AnnotationConfigApplicationContext(ImportingConfiguration.class).close())
.satisfies((ex) -> { .satisfies((ex) -> {
Throwable beanTypeDeductionException = findNestedCause(ex, BeanTypeDeductionException.class); Throwable beanTypeDeductionException = findNestedCause(ex, BeanTypeDeductionException.class);
assertThat(beanTypeDeductionException).isNotNull();
assertThat(beanTypeDeductionException).hasMessage("Failed to deduce bean type for " assertThat(beanTypeDeductionException).hasMessage("Failed to deduce bean type for "
+ OnMissingBeanConfiguration.class.getName() + ".objectMapper"); + OnMissingBeanConfiguration.class.getName() + ".objectMapper");
assertThat(findNestedCause(beanTypeDeductionException, NoClassDefFoundError.class)).isNotNull(); assertThat(findNestedCause(beanTypeDeductionException, NoClassDefFoundError.class)).isNotNull();
@ -52,7 +54,7 @@ class OnBeanConditionTypeDeductionFailureTests {
}); });
} }
private Throwable findNestedCause(Throwable ex, Class<? extends Throwable> target) { private @Nullable Throwable findNestedCause(Throwable ex, Class<? extends Throwable> target) {
Throwable candidate = ex; Throwable candidate = ex;
while (candidate != null) { while (candidate != null) {
if (target.isInstance(candidate)) { if (target.isInstance(candidate)) {

View File

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.condition; package org.springframework.boot.autoconfigure.condition;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -36,7 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
class ResourceConditionTests { class ResourceConditionTests {
private ConfigurableApplicationContext context; private @Nullable ConfigurableApplicationContext context;
@AfterEach @AfterEach
void tearDown() { void tearDown() {
@ -49,19 +50,19 @@ class ResourceConditionTests {
@WithResource(name = "logging.properties") @WithResource(name = "logging.properties")
void defaultResourceAndNoExplicitKey() { void defaultResourceAndNoExplicitKey() {
load(DefaultLocationConfiguration.class); load(DefaultLocationConfiguration.class);
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(isContainsBean()).isTrue();
} }
@Test @Test
void unknownDefaultLocationAndNoExplicitKey() { void unknownDefaultLocationAndNoExplicitKey() {
load(UnknownDefaultLocationConfiguration.class); load(UnknownDefaultLocationConfiguration.class);
assertThat(this.context.containsBean("foo")).isFalse(); assertThat(isContainsBean()).isFalse();
} }
@Test @Test
void unknownDefaultLocationAndExplicitKeyToResource() { void unknownDefaultLocationAndExplicitKeyToResource() {
load(UnknownDefaultLocationConfiguration.class, "spring.foo.test.config=logging.properties"); load(UnknownDefaultLocationConfiguration.class, "spring.foo.test.config=logging.properties");
assertThat(this.context.containsBean("foo")).isTrue(); assertThat(isContainsBean()).isTrue();
} }
private void load(Class<?> config, String... environment) { private void load(Class<?> config, String... environment) {
@ -72,6 +73,11 @@ class ResourceConditionTests {
this.context = applicationContext; this.context = applicationContext;
} }
private boolean isContainsBean() {
assertThat(this.context).isNotNull();
return this.context.containsBean("foo");
}
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@Conditional(DefaultLocationResourceCondition.class) @Conditional(DefaultLocationResourceCondition.class)
static class DefaultLocationConfiguration { static class DefaultLocationConfiguration {

View File

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.context; package org.springframework.boot.autoconfigure.context;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -35,7 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
class ConfigurationPropertiesAutoConfigurationTests { class ConfigurationPropertiesAutoConfigurationTests {
private AnnotationConfigApplicationContext context; private @Nullable AnnotationConfigApplicationContext context;
@AfterEach @AfterEach
void tearDown() { void tearDown() {
@ -47,13 +48,13 @@ class ConfigurationPropertiesAutoConfigurationTests {
@Test @Test
void processAnnotatedBean() { void processAnnotatedBean() {
load(new Class<?>[] { AutoConfig.class, SampleBean.class }, "foo.name:test"); load(new Class<?>[] { AutoConfig.class, SampleBean.class }, "foo.name:test");
assertThat(this.context.getBean(SampleBean.class).getName()).isEqualTo("test"); assertThat(getBean().getName()).isEqualTo("test");
} }
@Test @Test
void processAnnotatedBeanNoAutoConfig() { void processAnnotatedBeanNoAutoConfig() {
load(new Class<?>[] { SampleBean.class }, "foo.name:test"); load(new Class<?>[] { SampleBean.class }, "foo.name:test");
assertThat(this.context.getBean(SampleBean.class).getName()).isEqualTo("default"); assertThat(getBean().getName()).isEqualTo("default");
} }
private void load(Class<?>[] configs, String... environment) { private void load(Class<?>[] configs, String... environment) {
@ -63,6 +64,11 @@ class ConfigurationPropertiesAutoConfigurationTests {
this.context.refresh(); this.context.refresh();
} }
private SampleBean getBean() {
assertThat(this.context).isNotNull();
return this.context.getBean(SampleBean.class);
}
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(ConfigurationPropertiesAutoConfiguration.class) @ImportAutoConfiguration(ConfigurationPropertiesAutoConfiguration.class)
static class AutoConfig { static class AutoConfig {

View File

@ -22,6 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.util.Locale; import java.util.Locale;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -35,6 +36,7 @@ import org.springframework.boot.test.context.runner.ContextConsumer;
import org.springframework.boot.testsupport.classpath.resources.WithResource; import org.springframework.boot.testsupport.classpath.resources.WithResource;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceResolvable; import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
@ -267,18 +269,23 @@ class MessageSourceAutoConfigurationTests {
static class TestMessageSource implements MessageSource { static class TestMessageSource implements MessageSource {
@Override @Override
public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) { public String getMessage(String code, Object @Nullable [] args, @Nullable String defaultMessage,
@Nullable Locale locale) {
return code; return code;
} }
@Override @Override
public String getMessage(String code, Object[] args, Locale locale) { public String getMessage(String code, Object @Nullable [] args, @Nullable Locale locale) {
return code; return code;
} }
@Override @Override
public String getMessage(MessageSourceResolvable resolvable, Locale locale) { public String getMessage(MessageSourceResolvable resolvable, @Nullable Locale locale) {
return resolvable.getCodes()[0]; String[] codes = resolvable.getCodes();
if (codes == null) {
throw new NoSuchMessageException("codes is null");
}
return codes[0];
} }
} }

View File

@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.context; package org.springframework.boot.autoconfigure.context;
import java.util.Properties;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -99,6 +101,7 @@ class PropertyPlaceholderAutoConfigurationTests {
static class PlaceholderConfig { static class PlaceholderConfig {
@Value("${fruit:apple}") @Value("${fruit:apple}")
@SuppressWarnings("NullAway.Init")
private String fruit; private String fruit;
} }
@ -119,8 +122,9 @@ class PropertyPlaceholderAutoConfigurationTests {
@Bean @Bean
static PropertySourcesPlaceholderConfigurer morePlaceholders() { static PropertySourcesPlaceholderConfigurer morePlaceholders() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
configurer Properties properties = StringUtils.splitArrayElementsIntoProperties(new String[] { "fruit=orange" }, "=");
.setProperties(StringUtils.splitArrayElementsIntoProperties(new String[] { "fruit=orange" }, "=")); assertThat(properties).isNotNull();
configurer.setProperties(properties);
configurer.setLocalOverride(true); configurer.setLocalOverride(true);
configurer.setOrder(0); configurer.setOrder(0);
return configurer; return configurer;

View File

@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.diagnostics.analyzer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.FatalBeanException; import org.springframework.beans.FatalBeanException;
@ -64,6 +65,7 @@ class NoSuchBeanDefinitionFailureAnalyzerTests {
@Test @Test
void failureAnalysisForNoMatchType() { void failureAnalysisForNoMatchType() {
FailureAnalysis analysis = analyzeFailure(createFailure(StringHandler.class)); FailureAnalysis analysis = analyzeFailure(createFailure(StringHandler.class));
assertThat(analysis).isNotNull();
assertDescriptionConstructorMissingType(analysis, StringHandler.class, 0, String.class); assertDescriptionConstructorMissingType(analysis, StringHandler.class, 0, String.class);
assertThat(analysis.getDescription()) assertThat(analysis.getDescription())
.doesNotContain("No matching auto-configuration has been found for this type."); .doesNotContain("No matching auto-configuration has been found for this type.");
@ -74,6 +76,7 @@ class NoSuchBeanDefinitionFailureAnalyzerTests {
@Test @Test
void failureAnalysisForMissingPropertyExactType() { void failureAnalysisForMissingPropertyExactType() {
FailureAnalysis analysis = analyzeFailure(createFailure(StringPropertyTypeConfiguration.class)); FailureAnalysis analysis = analyzeFailure(createFailure(StringPropertyTypeConfiguration.class));
assertThat(analysis).isNotNull();
assertDescriptionConstructorMissingType(analysis, StringHandler.class, 0, String.class); assertDescriptionConstructorMissingType(analysis, StringHandler.class, 0, String.class);
assertBeanMethodDisabled(analysis, "did not find property 'spring.string.enabled'", assertBeanMethodDisabled(analysis, "did not find property 'spring.string.enabled'",
TestPropertyAutoConfiguration.class, "string"); TestPropertyAutoConfiguration.class, "string");
@ -93,6 +96,7 @@ class NoSuchBeanDefinitionFailureAnalyzerTests {
@Test @Test
void failureAnalysisForMissingClassOnAutoConfigurationType() { void failureAnalysisForMissingClassOnAutoConfigurationType() {
FailureAnalysis analysis = analyzeFailure(createFailure(MissingClassOnAutoConfigurationConfiguration.class)); FailureAnalysis analysis = analyzeFailure(createFailure(MissingClassOnAutoConfigurationConfiguration.class));
assertThat(analysis).isNotNull();
assertDescriptionConstructorMissingType(analysis, StringHandler.class, 0, String.class); assertDescriptionConstructorMissingType(analysis, StringHandler.class, 0, String.class);
assertClassDisabled(analysis, "did not find required class 'com.example.FooBar'", "string", assertClassDisabled(analysis, "did not find required class 'com.example.FooBar'", "string",
ClassUtils.getShortName(TestTypeClassAutoConfiguration.class)); ClassUtils.getShortName(TestTypeClassAutoConfiguration.class));
@ -104,6 +108,7 @@ class NoSuchBeanDefinitionFailureAnalyzerTests {
FatalBeanException failure = createFailure(StringHandler.class); FatalBeanException failure = createFailure(StringHandler.class);
addExclusions(this.analyzer, TestPropertyAutoConfiguration.class); addExclusions(this.analyzer, TestPropertyAutoConfiguration.class);
FailureAnalysis analysis = analyzeFailure(failure); FailureAnalysis analysis = analyzeFailure(failure);
assertThat(analysis).isNotNull();
assertDescriptionConstructorMissingType(analysis, StringHandler.class, 0, String.class); assertDescriptionConstructorMissingType(analysis, StringHandler.class, 0, String.class);
String configClass = ClassUtils.getShortName(TestPropertyAutoConfiguration.class.getName()); String configClass = ClassUtils.getShortName(TestPropertyAutoConfiguration.class.getName());
assertClassDisabled(analysis, String.format("auto-configuration '%s' was excluded", configClass), "string", assertClassDisabled(analysis, String.format("auto-configuration '%s' was excluded", configClass), "string",
@ -114,6 +119,7 @@ class NoSuchBeanDefinitionFailureAnalyzerTests {
@Test @Test
void failureAnalysisForSeveralConditionsType() { void failureAnalysisForSeveralConditionsType() {
FailureAnalysis analysis = analyzeFailure(createFailure(SeveralAutoConfigurationTypeConfiguration.class)); FailureAnalysis analysis = analyzeFailure(createFailure(SeveralAutoConfigurationTypeConfiguration.class));
assertThat(analysis).isNotNull();
assertDescriptionConstructorMissingType(analysis, StringHandler.class, 0, String.class); assertDescriptionConstructorMissingType(analysis, StringHandler.class, 0, String.class);
assertBeanMethodDisabled(analysis, "did not find property 'spring.string.enabled'", assertBeanMethodDisabled(analysis, "did not find property 'spring.string.enabled'",
TestPropertyAutoConfiguration.class, "string"); TestPropertyAutoConfiguration.class, "string");
@ -125,6 +131,7 @@ class NoSuchBeanDefinitionFailureAnalyzerTests {
@Test @Test
void failureAnalysisForNoMatchName() { void failureAnalysisForNoMatchName() {
FailureAnalysis analysis = analyzeFailure(createFailure(StringNameHandler.class)); FailureAnalysis analysis = analyzeFailure(createFailure(StringNameHandler.class));
assertThat(analysis).isNotNull();
assertThat(analysis.getDescription()) assertThat(analysis.getDescription())
.startsWith(String.format("Constructor in %s required a bean named '%s' that could not be found", .startsWith(String.format("Constructor in %s required a bean named '%s' that could not be found",
StringNameHandler.class.getName(), "test-string")); StringNameHandler.class.getName(), "test-string"));
@ -135,6 +142,7 @@ class NoSuchBeanDefinitionFailureAnalyzerTests {
@Test @Test
void failureAnalysisForMissingBeanName() { void failureAnalysisForMissingBeanName() {
FailureAnalysis analysis = analyzeFailure(createFailure(StringMissingBeanNameConfiguration.class)); FailureAnalysis analysis = analyzeFailure(createFailure(StringMissingBeanNameConfiguration.class));
assertThat(analysis).isNotNull();
assertThat(analysis.getDescription()) assertThat(analysis.getDescription())
.startsWith(String.format("Constructor in %s required a bean named '%s' that could not be found", .startsWith(String.format("Constructor in %s required a bean named '%s' that could not be found",
StringNameHandler.class.getName(), "test-string")); StringNameHandler.class.getName(), "test-string"));
@ -147,6 +155,7 @@ class NoSuchBeanDefinitionFailureAnalyzerTests {
@Test @Test
void failureAnalysisForNullBeanByType() { void failureAnalysisForNullBeanByType() {
FailureAnalysis analysis = analyzeFailure(createFailure(StringNullBeanConfiguration.class)); FailureAnalysis analysis = analyzeFailure(createFailure(StringNullBeanConfiguration.class));
assertThat(analysis).isNotNull();
assertDescriptionConstructorMissingType(analysis, StringHandler.class, 0, String.class); assertDescriptionConstructorMissingType(analysis, StringHandler.class, 0, String.class);
assertUserDefinedBean(analysis, "as the bean value is null", TestNullBeanConfiguration.class, "string"); assertUserDefinedBean(analysis, "as the bean value is null", TestNullBeanConfiguration.class, "string");
assertActionMissingType(analysis, String.class); assertActionMissingType(analysis, String.class);
@ -155,6 +164,7 @@ class NoSuchBeanDefinitionFailureAnalyzerTests {
@Test @Test
void failureAnalysisForUnmatchedQualifier() { void failureAnalysisForUnmatchedQualifier() {
FailureAnalysis analysis = analyzeFailure(createFailure(QualifiedBeanConfiguration.class)); FailureAnalysis analysis = analyzeFailure(createFailure(QualifiedBeanConfiguration.class));
assertThat(analysis).isNotNull();
assertThat(analysis.getDescription()) assertThat(analysis.getDescription())
.containsPattern("@org.springframework.beans.factory.annotation.Qualifier\\(\"*alpha\"*\\)"); .containsPattern("@org.springframework.beans.factory.annotation.Qualifier\\(\"*alpha\"*\\)");
} }
@ -204,6 +214,7 @@ class NoSuchBeanDefinitionFailureAnalyzerTests {
private static void addExclusions(NoSuchBeanDefinitionFailureAnalyzer analyzer, Class<?>... classes) { private static void addExclusions(NoSuchBeanDefinitionFailureAnalyzer analyzer, Class<?>... classes) {
ConditionEvaluationReport report = (ConditionEvaluationReport) ReflectionTestUtils.getField(analyzer, "report"); ConditionEvaluationReport report = (ConditionEvaluationReport) ReflectionTestUtils.getField(analyzer, "report");
assertThat(report).isNotNull();
List<String> exclusions = new ArrayList<>(report.getExclusions()); List<String> exclusions = new ArrayList<>(report.getExclusions());
for (Class<?> c : classes) { for (Class<?> c : classes) {
exclusions.add(c.getName()); exclusions.add(c.getName());
@ -216,14 +227,14 @@ class NoSuchBeanDefinitionFailureAnalyzerTests {
TestPropertyValues.of(environment).applyTo(this.context); TestPropertyValues.of(environment).applyTo(this.context);
this.context.register(config); this.context.register(config);
this.context.refresh(); this.context.refresh();
return null; throw new IllegalStateException("This should not be reached");
} }
catch (FatalBeanException ex) { catch (FatalBeanException ex) {
return ex; return ex;
} }
} }
private FailureAnalysis analyzeFailure(Exception failure) { private @Nullable FailureAnalysis analyzeFailure(Exception failure) {
FailureAnalysis analysis = this.analyzer.analyze(failure); FailureAnalysis analysis = this.analyzer.analyze(failure);
if (analysis != null) { if (analysis != null) {
new LoggingFailureAnalysisReporter().report(analysis); new LoggingFailureAnalysisReporter().report(analysis);
@ -316,7 +327,7 @@ class NoSuchBeanDefinitionFailureAnalyzerTests {
static class TestNullBeanConfiguration { static class TestNullBeanConfiguration {
@Bean @Bean
String string() { @Nullable String string() {
return null; return null;
} }

View File

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.info; package org.springframework.boot.autoconfigure.info;
import java.time.Instant;
import java.util.Properties; import java.util.Properties;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -105,7 +106,9 @@ class ProjectInfoAutoConfigurationTests {
assertThat(buildProperties.getArtifact()).isEqualTo("demo"); assertThat(buildProperties.getArtifact()).isEqualTo("demo");
assertThat(buildProperties.getName()).isEqualTo("Demo Project"); assertThat(buildProperties.getName()).isEqualTo("Demo Project");
assertThat(buildProperties.getVersion()).isEqualTo("0.0.1-SNAPSHOT"); assertThat(buildProperties.getVersion()).isEqualTo("0.0.1-SNAPSHOT");
assertThat(buildProperties.getTime().toEpochMilli()).isEqualTo(1457100965000L); Instant time = buildProperties.getTime();
assertThat(time).isNotNull();
assertThat(time.toEpochMilli()).isEqualTo(1457100965000L);
}); });
} }
@ -120,7 +123,9 @@ class ProjectInfoAutoConfigurationTests {
assertThat(buildProperties.getArtifact()).isEqualTo("acme"); assertThat(buildProperties.getArtifact()).isEqualTo("acme");
assertThat(buildProperties.getName()).isEqualTo("acme"); assertThat(buildProperties.getName()).isEqualTo("acme");
assertThat(buildProperties.getVersion()).isEqualTo("1.0.1-SNAPSHOT"); assertThat(buildProperties.getVersion()).isEqualTo("1.0.1-SNAPSHOT");
assertThat(buildProperties.getTime().toEpochMilli()).isEqualTo(1457088120000L); Instant time = buildProperties.getTime();
assertThat(time).isNotNull();
assertThat(time.toEpochMilli()).isEqualTo(1457088120000L);
}); });
} }

View File

@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.service.connection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactories.Registration; import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactories.Registration;
@ -145,7 +146,7 @@ class ConnectionDetailsFactoriesTests {
implements ConnectionDetailsFactory<String, TestConnectionDetails> { implements ConnectionDetailsFactory<String, TestConnectionDetails> {
@Override @Override
public TestConnectionDetails getConnectionDetails(String source) { public @Nullable TestConnectionDetails getConnectionDetails(String source) {
return null; return null;
} }

View File

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.ssl; package org.springframework.boot.autoconfigure.ssl;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.diagnostics.FailureAnalysis; import org.springframework.boot.diagnostics.FailureAnalysis;
@ -32,6 +33,7 @@ class BundleContentNotWatchableFailureAnalyzerTests {
@Test @Test
void shouldAnalyze() { void shouldAnalyze() {
FailureAnalysis failureAnalysis = performAnalysis(null); FailureAnalysis failureAnalysis = performAnalysis(null);
assertThat(failureAnalysis).isNotNull();
assertThat(failureAnalysis.getDescription()).isEqualTo( assertThat(failureAnalysis.getDescription()).isEqualTo(
"The content of 'name' is not watchable. Only 'file:' resources are watchable, but 'classpath:resource.pem' has been set"); "The content of 'name' is not watchable. Only 'file:' resources are watchable, but 'classpath:resource.pem' has been set");
assertThat(failureAnalysis.getAction()) assertThat(failureAnalysis.getAction())
@ -42,11 +44,12 @@ class BundleContentNotWatchableFailureAnalyzerTests {
@Test @Test
void shouldAnalyzeWithBundle() { void shouldAnalyzeWithBundle() {
FailureAnalysis failureAnalysis = performAnalysis("bundle-1"); FailureAnalysis failureAnalysis = performAnalysis("bundle-1");
assertThat(failureAnalysis).isNotNull();
assertThat(failureAnalysis.getDescription()).isEqualTo( assertThat(failureAnalysis.getDescription()).isEqualTo(
"The content of 'name' from bundle 'bundle-1' is not watchable'. Only 'file:' resources are watchable, but 'classpath:resource.pem' has been set"); "The content of 'name' from bundle 'bundle-1' is not watchable'. Only 'file:' resources are watchable, but 'classpath:resource.pem' has been set");
} }
private FailureAnalysis performAnalysis(String bundle) { private @Nullable FailureAnalysis performAnalysis(@Nullable String bundle) {
BundleContentNotWatchableException failure = new BundleContentNotWatchableException( BundleContentNotWatchableException failure = new BundleContentNotWatchableException(
new BundleContentProperty("name", "classpath:resource.pem")); new BundleContentProperty("name", "classpath:resource.pem"));
if (bundle != null) { if (bundle != null) {

View File

@ -31,6 +31,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@ -96,7 +98,7 @@ record CertificateMatchingTestSource(CertificateMatchingTestSource.Algorithm alg
* @param name the algorithm name * @param name the algorithm name
* @param spec the algorithm spec or {@code null} * @param spec the algorithm spec or {@code null}
*/ */
record Algorithm(String name, AlgorithmParameterSpec spec) { record Algorithm(String name, @Nullable AlgorithmParameterSpec spec) {
KeyPair generateKeyPair() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { KeyPair generateKeyPair() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
KeyPairGenerator generator = KeyPairGenerator.getInstance(this.name); KeyPairGenerator generator = KeyPairGenerator.getInstance(this.name);

View File

@ -68,13 +68,17 @@ class PropertiesSslBundleTests {
assertThat(sslBundle.getOptions().getCiphers()).containsExactlyInAnyOrder("cipher1", "cipher2", "cipher3"); assertThat(sslBundle.getOptions().getCiphers()).containsExactlyInAnyOrder("cipher1", "cipher2", "cipher3");
assertThat(sslBundle.getOptions().getEnabledProtocols()).containsExactlyInAnyOrder("protocol1", "protocol2"); assertThat(sslBundle.getOptions().getEnabledProtocols()).containsExactlyInAnyOrder("protocol1", "protocol2");
assertThat(sslBundle.getStores()).isNotNull(); assertThat(sslBundle.getStores()).isNotNull();
Certificate certificate = sslBundle.getStores().getKeyStore().getCertificate("alias"); KeyStore keyStore = sslBundle.getStores().getKeyStore();
assertThat(keyStore).isNotNull();
Certificate certificate = keyStore.getCertificate("alias");
assertThat(certificate).isNotNull(); assertThat(certificate).isNotNull();
assertThat(certificate.getType()).isEqualTo("X.509"); assertThat(certificate.getType()).isEqualTo("X.509");
Key key = sslBundle.getStores().getKeyStore().getKey("alias", "secret".toCharArray()); Key key = keyStore.getKey("alias", "secret".toCharArray());
assertThat(key).isNotNull(); assertThat(key).isNotNull();
assertThat(key.getAlgorithm()).isEqualTo("RSA"); assertThat(key.getAlgorithm()).isEqualTo("RSA");
certificate = sslBundle.getStores().getTrustStore().getCertificate("ssl"); KeyStore trustStore = sslBundle.getStores().getTrustStore();
assertThat(trustStore).isNotNull();
certificate = trustStore.getCertificate("ssl");
assertThat(certificate).isNotNull(); assertThat(certificate).isNotNull();
assertThat(certificate.getType()).isEqualTo("X.509"); assertThat(certificate.getType()).isEqualTo("X.509");
} }
@ -105,6 +109,7 @@ class PropertiesSslBundleTests {
.containsExactly("classpath:org/springframework/boot/autoconfigure/ssl/keystore.jks", "secret", "SUN", .containsExactly("classpath:org/springframework/boot/autoconfigure/ssl/keystore.jks", "secret", "SUN",
"JKS"); "JKS");
KeyStore trustStore = sslBundle.getStores().getTrustStore(); KeyStore trustStore = sslBundle.getStores().getTrustStore();
assertThat(trustStore).isNotNull();
assertThat(trustStore.getType()).isEqualTo("PKCS12"); assertThat(trustStore.getType()).isEqualTo("PKCS12");
assertThat(trustStore.getProvider().getName()).isEqualTo("SUN"); assertThat(trustStore.getProvider().getName()).isEqualTo("SUN");
} }

View File

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.ssl; package org.springframework.boot.autoconfigure.ssl;
import java.security.KeyStore;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -79,16 +80,24 @@ class SslAutoConfigurationTests {
assertThat(first.getManagers()).isNotNull(); assertThat(first.getManagers()).isNotNull();
assertThat(first.getKey().getAlias()).isEqualTo("alias1"); assertThat(first.getKey().getAlias()).isEqualTo("alias1");
assertThat(first.getKey().getPassword()).isEqualTo("secret1"); assertThat(first.getKey().getPassword()).isEqualTo("secret1");
assertThat(first.getStores().getKeyStore().getType()).isEqualTo("PKCS12"); KeyStore firstKeyStore = first.getStores().getKeyStore();
assertThat(first.getStores().getTrustStore().getType()).isEqualTo("PKCS12"); assertThat(firstKeyStore).isNotNull();
assertThat(firstKeyStore.getType()).isEqualTo("PKCS12");
KeyStore firstTrustStore = first.getStores().getTrustStore();
assertThat(firstTrustStore).isNotNull();
assertThat(firstTrustStore.getType()).isEqualTo("PKCS12");
SslBundle second = bundles.getBundle("second"); SslBundle second = bundles.getBundle("second");
assertThat(second).isNotNull(); assertThat(second).isNotNull();
assertThat(second.getStores()).isNotNull(); assertThat(second.getStores()).isNotNull();
assertThat(second.getManagers()).isNotNull(); assertThat(second.getManagers()).isNotNull();
assertThat(second.getKey().getAlias()).isEqualTo("alias2"); assertThat(second.getKey().getAlias()).isEqualTo("alias2");
assertThat(second.getKey().getPassword()).isEqualTo("secret2"); assertThat(second.getKey().getPassword()).isEqualTo("secret2");
assertThat(second.getStores().getKeyStore().getType()).isEqualTo("PKCS12"); KeyStore secondKeyStore = second.getStores().getKeyStore();
assertThat(second.getStores().getTrustStore().getType()).isEqualTo("PKCS12"); assertThat(secondKeyStore).isNotNull();
assertThat(secondKeyStore.getType()).isEqualTo("PKCS12");
KeyStore secondTrustStore = second.getStores().getTrustStore();
assertThat(secondTrustStore).isNotNull();
assertThat(secondTrustStore.getType()).isEqualTo("PKCS12");
}); });
} }
@ -114,8 +123,12 @@ class SslAutoConfigurationTests {
assertThat(bundle.getManagers()).isNotNull(); assertThat(bundle.getManagers()).isNotNull();
assertThat(bundle.getKey().getAlias()).isEqualTo("alias1"); assertThat(bundle.getKey().getAlias()).isEqualTo("alias1");
assertThat(bundle.getKey().getPassword()).isEqualTo("secret1"); assertThat(bundle.getKey().getPassword()).isEqualTo("secret1");
assertThat(bundle.getStores().getKeyStore().getType()).isEqualTo("PKCS12"); KeyStore keyStore = bundle.getStores().getKeyStore();
assertThat(bundle.getStores().getTrustStore().getType()).isEqualTo("PKCS12"); assertThat(keyStore).isNotNull();
assertThat(keyStore.getType()).isEqualTo("PKCS12");
KeyStore trustStore = bundle.getStores().getTrustStore();
assertThat(trustStore).isNotNull();
assertThat(trustStore.getType()).isEqualTo("PKCS12");
}); });
} }
@ -132,8 +145,12 @@ class SslAutoConfigurationTests {
assertThat(context).hasSingleBean(SslBundles.class); assertThat(context).hasSingleBean(SslBundles.class);
SslBundles bundles = context.getBean(SslBundles.class); SslBundles bundles = context.getBean(SslBundles.class);
SslBundle bundle = bundles.getBundle("test"); SslBundle bundle = bundles.getBundle("test");
assertThat(bundle.getStores().getKeyStore().getCertificate("alias1")).isNotNull(); KeyStore keyStore = bundle.getStores().getKeyStore();
assertThat(bundle.getStores().getTrustStore().getCertificate("ssl")).isNotNull(); assertThat(keyStore).isNotNull();
assertThat(keyStore.getCertificate("alias1")).isNotNull();
KeyStore trustStore = bundle.getStores().getTrustStore();
assertThat(trustStore).isNotNull();
assertThat(trustStore.getCertificate("ssl")).isNotNull();
}); });
} }

View File

@ -525,6 +525,7 @@ class TaskExecutionAutoConfigurationTests {
}); });
assertThat(latch.await(30, TimeUnit.SECONDS)).isTrue(); assertThat(latch.await(30, TimeUnit.SECONDS)).isTrue();
Thread thread = threadReference.get(); Thread thread = threadReference.get();
assertThat(thread).isNotNull();
assertThat(thread).extracting("virtual").as("%s is virtual", thread).isEqualTo(true); assertThat(thread).extracting("virtual").as("%s is virtual", thread).isEqualTo(true);
return thread.getName(); return thread.getName();
} }

View File

@ -53,6 +53,7 @@ class TemplateAvailabilityProvidersTests {
private TemplateAvailabilityProviders providers; private TemplateAvailabilityProviders providers;
@Mock @Mock
@SuppressWarnings("NullAway.Init")
private TemplateAvailabilityProvider provider; private TemplateAvailabilityProvider provider;
private final String view = "view"; private final String view = "view";
@ -62,6 +63,7 @@ class TemplateAvailabilityProvidersTests {
private final MockEnvironment environment = new MockEnvironment(); private final MockEnvironment environment = new MockEnvironment();
@Mock @Mock
@SuppressWarnings("NullAway.Init")
private ResourceLoader resourceLoader; private ResourceLoader resourceLoader;
@BeforeEach @BeforeEach
@ -70,6 +72,7 @@ class TemplateAvailabilityProvidersTests {
} }
@Test @Test
@SuppressWarnings("NullAway") // Test null check
void createWhenApplicationContextIsNullShouldThrowException() { void createWhenApplicationContextIsNullShouldThrowException() {
assertThatIllegalArgumentException() assertThatIllegalArgumentException()
.isThrownBy(() -> new TemplateAvailabilityProviders((ApplicationContext) null)) .isThrownBy(() -> new TemplateAvailabilityProviders((ApplicationContext) null))
@ -89,6 +92,7 @@ class TemplateAvailabilityProvidersTests {
} }
@Test @Test
@SuppressWarnings("NullAway") // Test null check
void createWhenClassLoaderIsNullShouldThrowException() { void createWhenClassLoaderIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new TemplateAvailabilityProviders((ClassLoader) null)) assertThatIllegalArgumentException().isThrownBy(() -> new TemplateAvailabilityProviders((ClassLoader) null))
.withMessageContaining("'classLoader' must not be null"); .withMessageContaining("'classLoader' must not be null");
@ -103,6 +107,7 @@ class TemplateAvailabilityProvidersTests {
} }
@Test @Test
@SuppressWarnings("NullAway") // Test null check
void createWhenProvidersIsNullShouldThrowException() { void createWhenProvidersIsNullShouldThrowException() {
assertThatIllegalArgumentException() assertThatIllegalArgumentException()
.isThrownBy(() -> new TemplateAvailabilityProviders((Collection<TemplateAvailabilityProvider>) null)) .isThrownBy(() -> new TemplateAvailabilityProviders((Collection<TemplateAvailabilityProvider>) null))
@ -117,12 +122,14 @@ class TemplateAvailabilityProvidersTests {
} }
@Test @Test
@SuppressWarnings("NullAway") // Test null check
void getProviderWhenApplicationContextIsNullShouldThrowException() { void getProviderWhenApplicationContextIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.providers.getProvider(this.view, null)) assertThatIllegalArgumentException().isThrownBy(() -> this.providers.getProvider(this.view, null))
.withMessageContaining("'applicationContext' must not be null"); .withMessageContaining("'applicationContext' must not be null");
} }
@Test @Test
@SuppressWarnings("NullAway") // Test null check
void getProviderWhenViewIsNullShouldThrowException() { void getProviderWhenViewIsNullShouldThrowException() {
assertThatIllegalArgumentException() assertThatIllegalArgumentException()
.isThrownBy(() -> this.providers.getProvider(null, this.environment, this.classLoader, this.resourceLoader)) .isThrownBy(() -> this.providers.getProvider(null, this.environment, this.classLoader, this.resourceLoader))
@ -130,6 +137,7 @@ class TemplateAvailabilityProvidersTests {
} }
@Test @Test
@SuppressWarnings("NullAway") // Test null check
void getProviderWhenEnvironmentIsNullShouldThrowException() { void getProviderWhenEnvironmentIsNullShouldThrowException() {
assertThatIllegalArgumentException() assertThatIllegalArgumentException()
.isThrownBy(() -> this.providers.getProvider(this.view, null, this.classLoader, this.resourceLoader)) .isThrownBy(() -> this.providers.getProvider(this.view, null, this.classLoader, this.resourceLoader))
@ -137,6 +145,7 @@ class TemplateAvailabilityProvidersTests {
} }
@Test @Test
@SuppressWarnings("NullAway") // Test null check
void getProviderWhenClassLoaderIsNullShouldThrowException() { void getProviderWhenClassLoaderIsNullShouldThrowException() {
assertThatIllegalArgumentException() assertThatIllegalArgumentException()
.isThrownBy(() -> this.providers.getProvider(this.view, this.environment, null, this.resourceLoader)) .isThrownBy(() -> this.providers.getProvider(this.view, this.environment, null, this.resourceLoader))
@ -144,6 +153,7 @@ class TemplateAvailabilityProvidersTests {
} }
@Test @Test
@SuppressWarnings("NullAway") // Test null check
void getProviderWhenResourceLoaderIsNullShouldThrowException() { void getProviderWhenResourceLoaderIsNullShouldThrowException() {
assertThatIllegalArgumentException() assertThatIllegalArgumentException()
.isThrownBy(() -> this.providers.getProvider(this.view, this.environment, this.classLoader, null)) .isThrownBy(() -> this.providers.getProvider(this.view, this.environment, this.classLoader, null))

View File

@ -90,6 +90,7 @@ class WebPropertiesResourcesTests {
properties.setStaleIfError(Duration.ofSeconds(6)); properties.setStaleIfError(Duration.ofSeconds(6));
properties.setStaleWhileRevalidate(Duration.ofSeconds(7)); properties.setStaleWhileRevalidate(Duration.ofSeconds(7));
CacheControl cacheControl = properties.toHttpCacheControl(); CacheControl cacheControl = properties.toHttpCacheControl();
assertThat(cacheControl).isNotNull();
assertThat(cacheControl.getHeaderValue()) assertThat(cacheControl.getHeaderValue())
.isEqualTo("max-age=4, must-revalidate, no-transform, public, private, proxy-revalidate," .isEqualTo("max-age=4, must-revalidate, no-transform, public, private, proxy-revalidate,"
+ " s-maxage=5, stale-if-error=6, stale-while-revalidate=7"); + " s-maxage=5, stale-if-error=6, stale-while-revalidate=7");
@ -101,6 +102,7 @@ class WebPropertiesResourcesTests {
properties.setMaxAge(Duration.ofSeconds(4)); properties.setMaxAge(Duration.ofSeconds(4));
properties.setNoStore(true); properties.setNoStore(true);
CacheControl cacheControl = properties.toHttpCacheControl(); CacheControl cacheControl = properties.toHttpCacheControl();
assertThat(cacheControl).isNotNull();
assertThat(cacheControl.getHeaderValue()).isEqualTo("no-store"); assertThat(cacheControl.getHeaderValue()).isEqualTo("no-store");
} }

View File

@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.ResourcePatternHint; import org.springframework.aot.hint.ResourcePatternHint;
@ -79,7 +80,7 @@ class WebResourcesRuntimeHintsTests {
} }
@Override @Override
public URL getResource(String name) { public @Nullable URL getResource(String name) {
return (this.availableResources.contains(name)) ? super.getResource("web/custom-resource.txt") : null; return (this.availableResources.contains(name)) ? super.getResource("web/custom-resource.txt") : null;
} }