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 {
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.List;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@ -42,7 +43,7 @@ class AutoConfigurationExcludeFilterTests {
private static final Class<?> FILTERED = ExampleFilteredAutoConfiguration.class;
private AnnotationConfigApplicationContext context;
private @Nullable AnnotationConfigApplicationContext context;
@AfterEach
void cleanUp() {
@ -56,7 +57,10 @@ class AutoConfigurationExcludeFilterTests {
this.context = new AnnotationConfigApplicationContext(Config.class);
assertThat(this.context.getBeansOfType(String.class)).hasSize(1);
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)

View File

@ -28,6 +28,7 @@ import java.util.Set;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -83,39 +84,35 @@ class AutoConfigurationImportSelectorTests {
void importsAreSelectedWhenUsingEnableAutoConfiguration() {
String[] imports = selectImports(BasicEnableAutoConfiguration.class);
assertThat(imports).hasSameSizeAs(getAutoConfigurationClassNames());
assertThat(this.importSelector.getLastEvent().getExclusions()).isEmpty();
assertThat(getLastEvent().getExclusions()).isEmpty();
}
@Test
void classExclusionsAreApplied() {
String[] imports = selectImports(EnableAutoConfigurationWithClassExclusions.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1);
assertThat(this.importSelector.getLastEvent().getExclusions())
.contains(SeventhAutoConfiguration.class.getName());
assertThat(getLastEvent().getExclusions()).contains(SeventhAutoConfiguration.class.getName());
}
@Test
void classExclusionsAreAppliedWhenUsingSpringBootApplication() {
String[] imports = selectImports(SpringBootApplicationWithClassExclusions.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1);
assertThat(this.importSelector.getLastEvent().getExclusions())
.contains(SeventhAutoConfiguration.class.getName());
assertThat(getLastEvent().getExclusions()).contains(SeventhAutoConfiguration.class.getName());
}
@Test
void classNamesExclusionsAreApplied() {
String[] imports = selectImports(EnableAutoConfigurationWithClassNameExclusions.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1);
assertThat(this.importSelector.getLastEvent().getExclusions())
.contains("com.example.one.FirstAutoConfiguration");
assertThat(getLastEvent().getExclusions()).contains("com.example.one.FirstAutoConfiguration");
}
@Test
void classNamesExclusionsAreAppliedWhenUsingSpringBootApplication() {
String[] imports = selectImports(SpringBootApplicationWithClassNameExclusions.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1);
assertThat(this.importSelector.getLastEvent().getExclusions())
.contains("com.example.three.ThirdAutoConfiguration");
assertThat(getLastEvent().getExclusions()).contains("com.example.three.ThirdAutoConfiguration");
}
@Test
@ -123,8 +120,7 @@ class AutoConfigurationImportSelectorTests {
this.environment.setProperty("spring.autoconfigure.exclude", "com.example.three.ThirdAutoConfiguration");
String[] imports = selectImports(BasicEnableAutoConfiguration.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1);
assertThat(this.importSelector.getLastEvent().getExclusions())
.contains("com.example.three.ThirdAutoConfiguration");
assertThat(getLastEvent().getExclusions()).contains("com.example.three.ThirdAutoConfiguration");
}
@Test
@ -151,8 +147,8 @@ class AutoConfigurationImportSelectorTests {
private void testSeveralPropertyExclusionsAreApplied() {
String[] imports = selectImports(BasicEnableAutoConfiguration.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 2);
assertThat(this.importSelector.getLastEvent().getExclusions())
.contains("com.example.two.SecondAutoConfiguration", "com.example.four.FourthAutoConfiguration");
assertThat(getLastEvent().getExclusions()).contains("com.example.two.SecondAutoConfiguration",
"com.example.four.FourthAutoConfiguration");
}
@Test
@ -160,9 +156,8 @@ class AutoConfigurationImportSelectorTests {
this.environment.setProperty("spring.autoconfigure.exclude", "com.example.one.FirstAutoConfiguration");
String[] imports = selectImports(EnableAutoConfigurationWithClassAndClassNameExclusions.class);
assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 3);
assertThat(this.importSelector.getLastEvent().getExclusions()).contains(
"com.example.one.FirstAutoConfiguration", "com.example.five.FifthAutoConfiguration",
SeventhAutoConfiguration.class.getName());
assertThat(getLastEvent().getExclusions()).contains("com.example.one.FirstAutoConfiguration",
"com.example.five.FifthAutoConfiguration", SeventhAutoConfiguration.class.getName());
}
@Test
@ -202,7 +197,7 @@ class AutoConfigurationImportSelectorTests {
this.environment.setProperty("spring.autoconfigure.exclude",
"org.springframework.boot.autoconfigure.DoesNotExist2");
selectImports(EnableAutoConfigurationWithAbsentClassNameExclude.class);
assertThat(this.importSelector.getLastEvent().getExclusions()).containsExactlyInAnyOrder(
assertThat(getLastEvent().getExclusions()).containsExactlyInAnyOrder(
"org.springframework.boot.autoconfigure.DoesNotExist1",
"org.springframework.boot.autoconfigure.DoesNotExist2");
}
@ -269,11 +264,17 @@ class AutoConfigurationImportSelectorTests {
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 AutoConfigurationImportEvent lastEvent;
private @Nullable AutoConfigurationImportEvent lastEvent;
TestAutoConfigurationImportSelector(Class<?> autoConfigurationAnnotation) {
TestAutoConfigurationImportSelector(@Nullable Class<?> autoConfigurationAnnotation) {
super(autoConfigurationAnnotation);
}
@ -287,7 +288,7 @@ class AutoConfigurationImportSelectorTests {
return Collections.singletonList((event) -> this.lastEvent = event);
}
AutoConfigurationImportEvent getLastEvent() {
@Nullable AutoConfigurationImportEvent getLastEvent() {
return this.lastEvent;
}
@ -297,6 +298,7 @@ class AutoConfigurationImportSelectorTests {
private final Set<String> nonMatching = new HashSet<>();
@SuppressWarnings("NullAway.Init")
private BeanFactory beanFactory;
TestAutoConfigurationImportFilter(String[] configurations, int... nonMatching) {
@ -306,7 +308,8 @@ class AutoConfigurationImportSelectorTests {
}
@Override
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
public boolean[] match(@Nullable String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
boolean[] result = new boolean[autoConfigurationClasses.length];
for (int i = 0; i < result.length; 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.function.UnaryOperator;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -251,10 +252,14 @@ class AutoConfigurationSorterTests {
}
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);
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()) {
properties.put(className + ".AutoConfigureAfter", value);
}
@ -263,11 +268,14 @@ class AutoConfigurationSorterTests {
private void addAutoConfigureBefore(Properties properties, String className,
AnnotationMetadata annotationMetadata) {
Map<String, Object> autoConfigureBefore = annotationMetadata
Map<String, @Nullable Object> autoConfigureBefore = annotationMetadata
.getAnnotationAttributes(AutoConfigureBefore.class.getName(), true);
if (autoConfigureBefore != null) {
String value = merge((String[]) autoConfigureBefore.get("value"),
(String[]) autoConfigureBefore.get("name"));
String[] valueAttribute = (String[]) autoConfigureBefore.get("value");
String[] nameAttribute = (String[]) autoConfigureBefore.get("name");
assertThat(valueAttribute).isNotNull();
assertThat(nameAttribute).isNotNull();
String value = merge(valueAttribute, nameAttribute);
if (!value.isEmpty()) {
properties.put(className + ".AutoConfigureBefore", value);
}
@ -275,7 +283,7 @@ class AutoConfigurationSorterTests {
}
private void addAutoConfigureOrder(Properties properties, String className, AnnotationMetadata annotationMetadata) {
Map<String, Object> autoConfigureOrder = annotationMetadata
Map<String, @Nullable Object> autoConfigureOrder = annotationMetadata
.getAnnotationAttributes(AutoConfigureOrder.class.getName());
if (autoConfigureOrder != null) {
Integer order = (Integer) autoConfigureOrder.get("order");

View File

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

View File

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

View File

@ -44,7 +44,9 @@ class AbstractNestedConditionTests {
void invalidMemberPhase() {
this.contextRunner.withUserConfiguration(InvalidConfig.class).run((context) -> {
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()
+ " uses a configuration phase that is inappropriate for class "
+ OnBeanCondition.class.getName());
@ -55,7 +57,9 @@ class AbstractNestedConditionTests {
void invalidNestedMemberPhase() {
this.contextRunner.withUserConfiguration(DoubleNestedConfig.class).run((context) -> {
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()
+ " uses a configuration phase that is inappropriate for class "
+ ValidNestedCondition.class.getName());

View File

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

View File

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

View File

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

View File

@ -21,6 +21,7 @@ import java.util.Map;
import javax.naming.Context;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
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.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.AnnotatedTypeMetadata;
@ -47,7 +49,7 @@ class ConditionalOnJndiTests {
private ClassLoader threadContextClassLoader;
private String initialContextFactory;
private @Nullable String initialContextFactory;
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();
@ -101,14 +103,16 @@ class ConditionalOnJndiTests {
@Test
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();
}
@Test
void jndiLocationFound() {
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();
}
@ -151,7 +155,7 @@ class ConditionalOnJndiTests {
private final boolean jndiAvailable = true;
private String foundLocation;
private @Nullable String foundLocation;
@Override
protected boolean isJndiAvailable() {
@ -162,7 +166,7 @@ class ConditionalOnJndiTests {
protected JndiLocator getJndiLocator(String[] locations) {
return new JndiLocator(locations) {
@Override
public String lookupFirstLocation() {
public @Nullable String lookupFirstLocation() {
return MockableOnJndi.this.foundLocation;
}
};

View File

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

View File

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

View File

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

View File

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

View File

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.context;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@ -35,7 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
class ConfigurationPropertiesAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
private @Nullable AnnotationConfigApplicationContext context;
@AfterEach
void tearDown() {
@ -47,13 +48,13 @@ class ConfigurationPropertiesAutoConfigurationTests {
@Test
void processAnnotatedBean() {
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
void processAnnotatedBeanNoAutoConfig() {
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) {
@ -63,6 +64,11 @@ class ConfigurationPropertiesAutoConfigurationTests {
this.context.refresh();
}
private SampleBean getBean() {
assertThat(this.context).isNotNull();
return this.context.getBean(SampleBean.class);
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(ConfigurationPropertiesAutoConfiguration.class)
static class AutoConfig {

View File

@ -22,6 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Locale;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Disabled;
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.context.MessageSource;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@ -267,18 +269,23 @@ class MessageSourceAutoConfigurationTests {
static class TestMessageSource implements MessageSource {
@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;
}
@Override
public String getMessage(String code, Object[] args, Locale locale) {
public String getMessage(String code, Object @Nullable [] args, @Nullable Locale locale) {
return code;
}
@Override
public String getMessage(MessageSourceResolvable resolvable, Locale locale) {
return resolvable.getCodes()[0];
public String getMessage(MessageSourceResolvable resolvable, @Nullable Locale locale) {
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;
import java.util.Properties;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
@ -99,6 +101,7 @@ class PropertyPlaceholderAutoConfigurationTests {
static class PlaceholderConfig {
@Value("${fruit:apple}")
@SuppressWarnings("NullAway.Init")
private String fruit;
}
@ -119,8 +122,9 @@ class PropertyPlaceholderAutoConfigurationTests {
@Bean
static PropertySourcesPlaceholderConfigurer morePlaceholders() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
configurer
.setProperties(StringUtils.splitArrayElementsIntoProperties(new String[] { "fruit=orange" }, "="));
Properties properties = StringUtils.splitArrayElementsIntoProperties(new String[] { "fruit=orange" }, "=");
assertThat(properties).isNotNull();
configurer.setProperties(properties);
configurer.setLocalOverride(true);
configurer.setOrder(0);
return configurer;

View File

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

View File

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.info;
import java.time.Instant;
import java.util.Properties;
import org.junit.jupiter.api.Test;
@ -105,7 +106,9 @@ class ProjectInfoAutoConfigurationTests {
assertThat(buildProperties.getArtifact()).isEqualTo("demo");
assertThat(buildProperties.getName()).isEqualTo("Demo Project");
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.getName()).isEqualTo("acme");
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.Map;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactories.Registration;
@ -145,7 +146,7 @@ class ConnectionDetailsFactoriesTests {
implements ConnectionDetailsFactory<String, TestConnectionDetails> {
@Override
public TestConnectionDetails getConnectionDetails(String source) {
public @Nullable TestConnectionDetails getConnectionDetails(String source) {
return null;
}

View File

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

View File

@ -31,6 +31,8 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
@ -96,7 +98,7 @@ record CertificateMatchingTestSource(CertificateMatchingTestSource.Algorithm alg
* @param name the algorithm name
* @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 {
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().getEnabledProtocols()).containsExactlyInAnyOrder("protocol1", "protocol2");
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.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.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.getType()).isEqualTo("X.509");
}
@ -105,6 +109,7 @@ class PropertiesSslBundleTests {
.containsExactly("classpath:org/springframework/boot/autoconfigure/ssl/keystore.jks", "secret", "SUN",
"JKS");
KeyStore trustStore = sslBundle.getStores().getTrustStore();
assertThat(trustStore).isNotNull();
assertThat(trustStore.getType()).isEqualTo("PKCS12");
assertThat(trustStore.getProvider().getName()).isEqualTo("SUN");
}

View File

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.ssl;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;
@ -79,16 +80,24 @@ class SslAutoConfigurationTests {
assertThat(first.getManagers()).isNotNull();
assertThat(first.getKey().getAlias()).isEqualTo("alias1");
assertThat(first.getKey().getPassword()).isEqualTo("secret1");
assertThat(first.getStores().getKeyStore().getType()).isEqualTo("PKCS12");
assertThat(first.getStores().getTrustStore().getType()).isEqualTo("PKCS12");
KeyStore firstKeyStore = first.getStores().getKeyStore();
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");
assertThat(second).isNotNull();
assertThat(second.getStores()).isNotNull();
assertThat(second.getManagers()).isNotNull();
assertThat(second.getKey().getAlias()).isEqualTo("alias2");
assertThat(second.getKey().getPassword()).isEqualTo("secret2");
assertThat(second.getStores().getKeyStore().getType()).isEqualTo("PKCS12");
assertThat(second.getStores().getTrustStore().getType()).isEqualTo("PKCS12");
KeyStore secondKeyStore = second.getStores().getKeyStore();
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.getKey().getAlias()).isEqualTo("alias1");
assertThat(bundle.getKey().getPassword()).isEqualTo("secret1");
assertThat(bundle.getStores().getKeyStore().getType()).isEqualTo("PKCS12");
assertThat(bundle.getStores().getTrustStore().getType()).isEqualTo("PKCS12");
KeyStore keyStore = bundle.getStores().getKeyStore();
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);
SslBundles bundles = context.getBean(SslBundles.class);
SslBundle bundle = bundles.getBundle("test");
assertThat(bundle.getStores().getKeyStore().getCertificate("alias1")).isNotNull();
assertThat(bundle.getStores().getTrustStore().getCertificate("ssl")).isNotNull();
KeyStore keyStore = bundle.getStores().getKeyStore();
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();
Thread thread = threadReference.get();
assertThat(thread).isNotNull();
assertThat(thread).extracting("virtual").as("%s is virtual", thread).isEqualTo(true);
return thread.getName();
}

View File

@ -53,6 +53,7 @@ class TemplateAvailabilityProvidersTests {
private TemplateAvailabilityProviders providers;
@Mock
@SuppressWarnings("NullAway.Init")
private TemplateAvailabilityProvider provider;
private final String view = "view";
@ -62,6 +63,7 @@ class TemplateAvailabilityProvidersTests {
private final MockEnvironment environment = new MockEnvironment();
@Mock
@SuppressWarnings("NullAway.Init")
private ResourceLoader resourceLoader;
@BeforeEach
@ -70,6 +72,7 @@ class TemplateAvailabilityProvidersTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenApplicationContextIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new TemplateAvailabilityProviders((ApplicationContext) null))
@ -89,6 +92,7 @@ class TemplateAvailabilityProvidersTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenClassLoaderIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new TemplateAvailabilityProviders((ClassLoader) null))
.withMessageContaining("'classLoader' must not be null");
@ -103,6 +107,7 @@ class TemplateAvailabilityProvidersTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void createWhenProvidersIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new TemplateAvailabilityProviders((Collection<TemplateAvailabilityProvider>) null))
@ -117,12 +122,14 @@ class TemplateAvailabilityProvidersTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void getProviderWhenApplicationContextIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.providers.getProvider(this.view, null))
.withMessageContaining("'applicationContext' must not be null");
}
@Test
@SuppressWarnings("NullAway") // Test null check
void getProviderWhenViewIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.providers.getProvider(null, this.environment, this.classLoader, this.resourceLoader))
@ -130,6 +137,7 @@ class TemplateAvailabilityProvidersTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void getProviderWhenEnvironmentIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.providers.getProvider(this.view, null, this.classLoader, this.resourceLoader))
@ -137,6 +145,7 @@ class TemplateAvailabilityProvidersTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void getProviderWhenClassLoaderIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.providers.getProvider(this.view, this.environment, null, this.resourceLoader))
@ -144,6 +153,7 @@ class TemplateAvailabilityProvidersTests {
}
@Test
@SuppressWarnings("NullAway") // Test null check
void getProviderWhenResourceLoaderIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.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.setStaleWhileRevalidate(Duration.ofSeconds(7));
CacheControl cacheControl = properties.toHttpCacheControl();
assertThat(cacheControl).isNotNull();
assertThat(cacheControl.getHeaderValue())
.isEqualTo("max-age=4, must-revalidate, no-transform, public, private, proxy-revalidate,"
+ " s-maxage=5, stale-if-error=6, stale-while-revalidate=7");
@ -101,6 +102,7 @@ class WebPropertiesResourcesTests {
properties.setMaxAge(Duration.ofSeconds(4));
properties.setNoStore(true);
CacheControl cacheControl = properties.toHttpCacheControl();
assertThat(cacheControl).isNotNull();
assertThat(cacheControl.getHeaderValue()).isEqualTo("no-store");
}

View File

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