Add nullability annotations to tests in core/spring-boot-docker-compose

See gh-47263
This commit is contained in:
Moritz Halbritter 2025-09-10 11:58:43 +02:00
parent 532ea9abc1
commit b566b73be6
12 changed files with 42 additions and 14 deletions

View File

@ -38,3 +38,11 @@ dependencies {
testFixturesImplementation(project(":test-support:spring-boot-docker-test-support")) testFixturesImplementation(project(":test-support:spring-boot-docker-test-support"))
} }
tasks.named("compileTestJava") {
options.nullability.checking = "tests"
}
tasks.named("compileDockerTestJava") {
options.nullability.checking = "tests"
}

View File

@ -27,6 +27,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.api.io.TempDir;
@ -88,7 +89,7 @@ class DefaultDockerComposeIntegrationTests {
} }
} }
private RunningService findService(List<RunningService> runningServices, String serviceName) { private @Nullable RunningService findService(List<RunningService> runningServices, String serviceName) {
for (RunningService runningService : runningServices) { for (RunningService runningService : runningServices) {
if (runningService.name().contains(serviceName)) { if (runningService.name().contains(serviceName)) {
return runningService; return runningService;

View File

@ -59,6 +59,7 @@ import static org.assertj.core.api.Assertions.assertThat;
class DockerCliIntegrationTests { class DockerCliIntegrationTests {
@TempDir @TempDir
@SuppressWarnings("NullAway.Init")
private static Path tempDir; private static Path tempDir;
@Test @Test

View File

@ -47,6 +47,7 @@ import static org.assertj.core.api.Assertions.entry;
class DefaultRunningServiceTests { class DefaultRunningServiceTests {
@TempDir @TempDir
@SuppressWarnings("NullAway.Init")
File temp; File temp;
private DefaultRunningService runningService; private DefaultRunningService runningService;
@ -126,7 +127,7 @@ class DefaultRunningServiceTests {
Map<String, ExposedPort> exposedPorts = Map.of("8080/tcp", new ExposedPort()); Map<String, ExposedPort> exposedPorts = Map.of("8080/tcp", new ExposedPort());
List<String> env = List.of("a=b"); List<String> env = List.of("a=b");
Config config = new Config(image, labels, exposedPorts, env); Config config = new Config(image, labels, exposedPorts, env);
Map<String, List<HostPort>> ports = Map.of("8080/tcp", List.of(new HostPort(null, "9090"))); Map<String, List<HostPort>> ports = Map.of("8080/tcp", List.of(new HostPort("127.0.0.1", "9090")));
NetworkSettings networkSettings = new NetworkSettings(ports); NetworkSettings networkSettings = new NetworkSettings(ports);
HostConfig hostConfig = new HostConfig("bridge"); HostConfig hostConfig = new HostConfig("bridge");
DockerCliInspectResponse inspectResponse = new DockerCliInspectResponse(id, config, networkSettings, DockerCliInspectResponse inspectResponse = new DockerCliInspectResponse(id, config, networkSettings,

View File

@ -39,6 +39,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
class DockerComposeFileTests { class DockerComposeFileTests {
@TempDir @TempDir
@SuppressWarnings("NullAway.Init")
File temp; File temp;
@Test @Test
@ -74,6 +75,7 @@ class DockerComposeFileTests {
File file = new File(this.temp, "docker-compose.yml").getCanonicalFile(); File file = new File(this.temp, "docker-compose.yml").getCanonicalFile();
FileCopyUtils.copy(new byte[0], file); FileCopyUtils.copy(new byte[0], file);
DockerComposeFile composeFile = DockerComposeFile.find(file.getParentFile()); DockerComposeFile composeFile = DockerComposeFile.find(file.getParentFile());
assertThat(composeFile).isNotNull();
assertThat(composeFile.getFiles()).containsExactly(file); assertThat(composeFile.getFiles()).containsExactly(file);
} }
@ -84,6 +86,7 @@ class DockerComposeFileTests {
File f2 = new File(this.temp, "compose.yml").getCanonicalFile(); File f2 = new File(this.temp, "compose.yml").getCanonicalFile();
FileCopyUtils.copy(new byte[0], f2); FileCopyUtils.copy(new byte[0], f2);
DockerComposeFile composeFile = DockerComposeFile.find(f1.getParentFile()); DockerComposeFile composeFile = DockerComposeFile.find(f1.getParentFile());
assertThat(composeFile).isNotNull();
assertThat(composeFile.getFiles()).containsExactly(f2); assertThat(composeFile.getFiles()).containsExactly(f2);
} }
@ -127,6 +130,7 @@ class DockerComposeFileTests {
} }
@Test @Test
@SuppressWarnings("NullAway") // Test null check
void ofWhenFileIsNullThrowsException() { void ofWhenFileIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> DockerComposeFile.of((File) null)) assertThatIllegalArgumentException().isThrownBy(() -> DockerComposeFile.of((File) null))
.withMessage("'file' must not be null"); .withMessage("'file' must not be null");

View File

@ -37,6 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
class DockerComposeOriginTests { class DockerComposeOriginTests {
@TempDir @TempDir
@SuppressWarnings("NullAway.Init")
File temp; File temp;
@Test @Test

View File

@ -23,6 +23,7 @@ import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -50,7 +51,7 @@ class DockerHostTests {
private static final String TCP_HOST = "tcp://192.168.1.1"; private static final String TCP_HOST = "tcp://192.168.1.1";
private static final Function<String, String> NO_SYSTEM_ENV = (key) -> null; private static final Function<String, @Nullable String> NO_SYSTEM_ENV = (key) -> null;
private static final Supplier<List<DockerCliContextResponse>> NO_CONTEXT = Collections::emptyList; private static final Supplier<List<DockerCliContextResponse>> NO_CONTEXT = Collections::emptyList;

View File

@ -116,6 +116,7 @@ class ImageNameTests {
} }
@Test @Test
@SuppressWarnings("NullAway") // Test null check
void ofWhenNameIsNullThrowsException() { void ofWhenNameIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> ImageName.of(null)) assertThatIllegalArgumentException().isThrownBy(() -> ImageName.of(null))
.withMessage("'value' must not be empty"); .withMessage("'value' must not be empty");

View File

@ -27,6 +27,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
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;
@ -68,15 +69,16 @@ import static org.mockito.Mockito.never;
class DockerComposeLifecycleManagerTests { class DockerComposeLifecycleManagerTests {
@TempDir @TempDir
@SuppressWarnings("NullAway.Init")
File temp; File temp;
private DockerComposeFile dockerComposeFile; private DockerComposeFile dockerComposeFile;
private DockerCompose dockerCompose; private DockerCompose dockerCompose;
private Set<String> activeProfiles; private @Nullable Set<String> activeProfiles;
private List<String> arguments; private @Nullable List<String> arguments;
private GenericApplicationContext applicationContext; private GenericApplicationContext applicationContext;
@ -84,7 +86,7 @@ class DockerComposeLifecycleManagerTests {
private ServiceReadinessChecks serviceReadinessChecks; private ServiceReadinessChecks serviceReadinessChecks;
private List<RunningService> runningServices; private @Nullable List<RunningService> runningServices;
private DockerComposeProperties properties; private DockerComposeProperties properties;
@ -316,6 +318,7 @@ class DockerComposeLifecycleManagerTests {
setUpRunningServices(); setUpRunningServices();
this.lifecycleManager.start(); this.lifecycleManager.start();
this.shutdownHandlers.run(); this.shutdownHandlers.run();
assertThat(this.runningServices).isNotNull();
then(this.serviceReadinessChecks).should().waitUntilReady(this.runningServices); then(this.serviceReadinessChecks).should().waitUntilReady(this.runningServices);
} }
@ -327,6 +330,7 @@ class DockerComposeLifecycleManagerTests {
setUpRunningServices(); setUpRunningServices();
this.lifecycleManager.start(); this.lifecycleManager.start();
this.shutdownHandlers.run(); this.shutdownHandlers.run();
assertThat(this.runningServices).isNotNull();
then(this.serviceReadinessChecks).should(never()).waitUntilReady(this.runningServices); then(this.serviceReadinessChecks).should(never()).waitUntilReady(this.runningServices);
} }
@ -339,6 +343,7 @@ class DockerComposeLifecycleManagerTests {
setUpRunningServices(); setUpRunningServices();
this.lifecycleManager.start(); this.lifecycleManager.start();
this.shutdownHandlers.run(); this.shutdownHandlers.run();
assertThat(this.runningServices).isNotNull();
then(this.serviceReadinessChecks).should(never()).waitUntilReady(this.runningServices); then(this.serviceReadinessChecks).should(never()).waitUntilReady(this.runningServices);
} }
@ -350,6 +355,7 @@ class DockerComposeLifecycleManagerTests {
setUpRunningServices(false); setUpRunningServices(false);
this.lifecycleManager.start(); this.lifecycleManager.start();
this.shutdownHandlers.run(); this.shutdownHandlers.run();
assertThat(this.runningServices).isNotNull();
then(this.serviceReadinessChecks).should().waitUntilReady(this.runningServices); then(this.serviceReadinessChecks).should().waitUntilReady(this.runningServices);
} }
@ -498,14 +504,14 @@ class DockerComposeLifecycleManagerTests {
*/ */
static class EventCapturingListener implements ApplicationListener<DockerComposeServicesReadyEvent> { static class EventCapturingListener implements ApplicationListener<DockerComposeServicesReadyEvent> {
private DockerComposeServicesReadyEvent event; private @Nullable DockerComposeServicesReadyEvent event;
@Override @Override
public void onApplicationEvent(DockerComposeServicesReadyEvent event) { public void onApplicationEvent(DockerComposeServicesReadyEvent event) {
this.event = event; this.event = event;
} }
DockerComposeServicesReadyEvent getEvent() { @Nullable DockerComposeServicesReadyEvent getEvent() {
return this.event; return this.event;
} }

View File

@ -18,6 +18,7 @@ package org.springframework.boot.docker.compose.lifecycle;
import java.util.Set; import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
@ -60,7 +61,7 @@ class DockerComposeListenerTests {
private final ConfigurableApplicationContext context; private final ConfigurableApplicationContext context;
private DockerComposeLifecycleManager manager; private @Nullable DockerComposeLifecycleManager manager;
TestDockerComposeListener(SpringApplicationShutdownHandlers shutdownHandlers, TestDockerComposeListener(SpringApplicationShutdownHandlers shutdownHandlers,
ConfigurableApplicationContext context) { ConfigurableApplicationContext context) {
@ -79,7 +80,7 @@ class DockerComposeListenerTests {
return this.manager; return this.manager;
} }
DockerComposeLifecycleManager getManager() { @Nullable DockerComposeLifecycleManager getManager() {
return this.manager; return this.manager;
} }

View File

@ -23,10 +23,12 @@ import java.util.ArrayList;
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.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.docker.compose.core.RunningService; import org.springframework.boot.docker.compose.core.RunningService;
import org.springframework.boot.docker.compose.lifecycle.DockerComposeProperties.Readiness.Tcp;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -103,7 +105,7 @@ class ServiceReadinessChecksTests {
*/ */
static class MockServiceReadinessCheck extends TcpConnectServiceReadinessCheck { static class MockServiceReadinessCheck extends TcpConnectServiceReadinessCheck {
private final Integer failUntil; private final @Nullable Integer failUntil;
private final List<RunningService> checked = new ArrayList<>(); private final List<RunningService> checked = new ArrayList<>();
@ -111,8 +113,8 @@ class ServiceReadinessChecksTests {
this(null); this(null);
} }
MockServiceReadinessCheck(Integer failUntil) { MockServiceReadinessCheck(@Nullable Integer failUntil) {
super(null); super(new Tcp());
this.failUntil = failUntil; this.failUntil = failUntil;
} }

View File

@ -19,6 +19,7 @@ package org.springframework.boot.docker.compose.service.connection;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate; import java.util.function.Predicate;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.docker.compose.core.ImageReference; import org.springframework.boot.docker.compose.core.ImageReference;
@ -96,7 +97,7 @@ class ConnectionNamePredicateTests {
return sourceOf(connectionName, null); return sourceOf(connectionName, null);
} }
private DockerComposeConnectionSource sourceOf(String connectionName, String label) { private DockerComposeConnectionSource sourceOf(String connectionName, @Nullable String label) {
DockerComposeConnectionSource source = mock(DockerComposeConnectionSource.class); DockerComposeConnectionSource source = mock(DockerComposeConnectionSource.class);
RunningService runningService = mock(RunningService.class); RunningService runningService = mock(RunningService.class);
given(source.getRunningService()).willReturn(runningService); given(source.getRunningService()).willReturn(runningService);