Improve null-safety of core/spring-boot-test

See gh-46926
This commit is contained in:
Moritz Halbritter 2025-08-18 11:44:03 +02:00
parent 7ad90fb963
commit 717ddac137
5 changed files with 17 additions and 12 deletions

View File

@ -40,7 +40,7 @@ import org.springframework.util.ClassUtils;
*/ */
public final class AnnotatedClassFinder { public final class AnnotatedClassFinder {
private static final Map<String, Class<?>> cache = Collections.synchronizedMap(new Cache(40)); private static final Map<String, @Nullable Class<?>> cache = Collections.synchronizedMap(new Cache(40));
private final Class<? extends Annotation> annotationType; private final Class<? extends Annotation> annotationType;
@ -110,7 +110,7 @@ public final class AnnotatedClassFinder {
/** /**
* Cache implementation based on {@link LinkedHashMap}. * Cache implementation based on {@link LinkedHashMap}.
*/ */
private static class Cache extends LinkedHashMap<String, Class<?>> { private static class Cache extends LinkedHashMap<String, @Nullable Class<?>> {
private final int maxSize; private final int maxSize;
@ -120,7 +120,7 @@ public final class AnnotatedClassFinder {
} }
@Override @Override
protected boolean removeEldestEntry(Map.Entry<String, Class<?>> eldest) { protected boolean removeEldestEntry(Map.Entry<String, @Nullable Class<?>> eldest) {
return size() > this.maxSize; return size() > this.maxSize;
} }

View File

@ -553,8 +553,10 @@ public class SpringBootContextLoader extends AbstractContextLoader implements Ao
@Override @Override
public void failed(@Nullable ConfigurableApplicationContext context, Throwable exception) { public void failed(@Nullable ConfigurableApplicationContext context, Throwable exception) {
if (context != null) {
ContextLoaderHook.this.failedContexts.add(context); ContextLoaderHook.this.failedContexts.add(context);
} }
}
}; };
} }

View File

@ -432,7 +432,7 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
this.runnerConfiguration.beanRegistrations.forEach((registration) -> registration.apply(context)); this.runnerConfiguration.beanRegistrations.forEach((registration) -> registration.apply(context));
this.runnerConfiguration.initializers.forEach((initializer) -> initializer.initialize(context)); this.runnerConfiguration.initializers.forEach((initializer) -> initializer.initialize(context));
if (!CollectionUtils.isEmpty(this.runnerConfiguration.configurations)) { if (!CollectionUtils.isEmpty(this.runnerConfiguration.configurations)) {
BiConsumer<Class<?>, String> registrar = getRegistrar(context); BiConsumer<Class<?>, @Nullable String> registrar = getRegistrar(context);
for (Configurations configurations : Configurations.collate(this.runnerConfiguration.configurations)) { for (Configurations configurations : Configurations.collate(this.runnerConfiguration.configurations)) {
for (Class<?> beanClass : Configurations.getClasses(configurations)) { for (Class<?> beanClass : Configurations.getClasses(configurations)) {
String beanName = configurations.getBeanName(beanClass); String beanName = configurations.getBeanName(beanClass);
@ -445,7 +445,7 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
} }
} }
private BiConsumer<Class<?>, String> getRegistrar(C context) { private BiConsumer<Class<?>, @Nullable String> getRegistrar(C context) {
if (context instanceof BeanDefinitionRegistry registry) { if (context instanceof BeanDefinitionRegistry registry) {
return new AnnotatedBeanDefinitionReader(registry, context.getEnvironment())::registerBean; return new AnnotatedBeanDefinitionReader(registry, context.getEnvironment())::registerBean;
} }

View File

@ -139,7 +139,10 @@ class OutputCapture implements CapturedOutput {
*/ */
void reset() { void reset() {
clearExisting(); clearExisting();
this.systemCaptures.peek().reset(); SystemCapture peeked = this.systemCaptures.peek();
if (peeked != null) {
peeked.reset();
}
} }
void clearExisting() { void clearExisting() {

View File

@ -56,9 +56,9 @@ public final class TestPropertyValues {
private static final TestPropertyValues EMPTY = new TestPropertyValues(Collections.emptyMap()); private static final TestPropertyValues EMPTY = new TestPropertyValues(Collections.emptyMap());
private final Map<String, Object> properties; private final Map<String, @Nullable Object> properties;
private TestPropertyValues(Map<String, Object> properties) { private TestPropertyValues(Map<String, @Nullable Object> properties) {
this.properties = Collections.unmodifiableMap(properties); this.properties = Collections.unmodifiableMap(properties);
} }
@ -117,7 +117,7 @@ public final class TestPropertyValues {
if (stream == null) { if (stream == null) {
return this; return this;
} }
Map<String, Object> properties = new LinkedHashMap<>(this.properties); Map<String, @Nullable Object> properties = new LinkedHashMap<>(this.properties);
stream.map(mapper).filter(Objects::nonNull).forEach((pair) -> pair.addTo(properties)); stream.map(mapper).filter(Objects::nonNull).forEach((pair) -> pair.addTo(properties));
return new TestPropertyValues(properties); return new TestPropertyValues(properties);
} }
@ -175,7 +175,7 @@ public final class TestPropertyValues {
public void applyToSystemProperties(Runnable action) { public void applyToSystemProperties(Runnable action) {
applyToSystemProperties(() -> { applyToSystemProperties(() -> {
action.run(); action.run();
return null; return new Object();
}); });
} }
@ -332,7 +332,7 @@ public final class TestPropertyValues {
this.value = value; this.value = value;
} }
public void addTo(Map<String, Object> properties) { public void addTo(Map<String, @Nullable Object> properties) {
properties.put(this.name, this.value); properties.put(this.name, this.value);
} }