Add nullability annotations to tests in cli/spring-boot-cli

See gh-47263
This commit is contained in:
Moritz Halbritter
2025-10-16 14:07:16 +02:00
parent 039fd0fa9a
commit 8108678bc5
8 changed files with 54 additions and 19 deletions
+8
View File
@@ -162,3 +162,11 @@ publishing {
eclipse.classpath { // https://github.com/eclipse/buildship/issues/939
plusConfigurations += [ configurations.compileOnlyProject ]
}
tasks.named("compileTestJava") {
options.nullability.checking = "tests"
}
tasks.named("compileIntTestJava") {
options.nullability.checking = "tests"
}
@@ -16,6 +16,7 @@
package org.springframework.boot.cli.command;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -58,7 +59,7 @@ class CommandRunnerIntegrationTests {
static class ArgHandlingCommand extends AbstractCommand {
private String[] args;
private String @Nullable [] args;
ArgHandlingCommand() {
super("args", "");
@@ -19,6 +19,7 @@ package org.springframework.boot.cli.command;
import java.util.EnumSet;
import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -47,9 +48,11 @@ class CommandRunnerTests {
private CommandRunner commandRunner;
@Mock
@SuppressWarnings("NullAway.Init")
private Command regularCommand;
@Mock
@SuppressWarnings("NullAway.Init")
private Command anotherCommand;
private final Set<Call> calls = EnumSet.noneOf(Call.class);
@@ -74,7 +77,7 @@ class CommandRunnerTests {
}
@Override
protected boolean errorMessage(String message) {
protected boolean errorMessage(@Nullable String message) {
CommandRunnerTests.this.calls.add(Call.ERROR_MESSAGE);
return super.errorMessage(message);
}
@@ -29,6 +29,7 @@ import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.message.BasicHeader;
import org.json.JSONException;
import org.json.JSONObject;
import org.jspecify.annotations.Nullable;
import org.mockito.ArgumentMatcher;
import org.springframework.core.io.ClassPathResource;
@@ -91,7 +92,7 @@ public abstract class AbstractHttpClientMockTests {
given(this.http.executeOpen(any(HttpHost.class), argThat(getForNonMetadata()), isNull())).willReturn(response);
}
protected void mockProjectGenerationError(int status, String message) throws IOException, JSONException {
protected void mockProjectGenerationError(int status, @Nullable String message) throws IOException, JSONException {
// Required for project generation as the metadata is read first
mockSuccessfulMetadataGet(false);
ClassicHttpResponse response = mock(ClassicHttpResponse.class);
@@ -107,7 +108,7 @@ public abstract class AbstractHttpClientMockTests {
given(this.http.executeOpen(any(HttpHost.class), isA(HttpGet.class), isNull())).willReturn(response);
}
protected HttpEntity mockHttpEntity(ClassicHttpResponse response, byte[] content, String contentType) {
protected HttpEntity mockHttpEntity(ClassicHttpResponse response, byte[] content, @Nullable String contentType) {
try {
HttpEntity entity = mock(HttpEntity.class);
given(entity.getContent()).willReturn(new ByteArrayInputStream(content));
@@ -126,7 +127,7 @@ public abstract class AbstractHttpClientMockTests {
given(response.getCode()).willReturn(status);
}
protected void mockHttpHeader(ClassicHttpResponse response, String headerName, String value) {
protected void mockHttpHeader(ClassicHttpResponse response, String headerName, @Nullable String value) {
Header header = (value != null) ? new BasicHeader(headerName, value) : null;
given(response.getFirstHeader(headerName)).willReturn(header);
}
@@ -146,7 +147,7 @@ public abstract class AbstractHttpClientMockTests {
return "attachment; filename=\"" + fileName + "\"";
}
private String createJsonError(int status, String message) throws JSONException {
private String createJsonError(int status, @Nullable String message) throws JSONException {
JSONObject json = new JSONObject();
json.put("status", status);
if (message != null) {
@@ -157,17 +158,17 @@ public abstract class AbstractHttpClientMockTests {
static class MockHttpProjectGenerationRequest {
String contentType;
@Nullable String contentType;
String fileName;
@Nullable String fileName;
byte[] content = new byte[] { 0, 0, 0, 0 };
MockHttpProjectGenerationRequest(String contentType, String fileName) {
MockHttpProjectGenerationRequest(@Nullable String contentType, @Nullable String fileName) {
this(contentType, fileName, new byte[] { 0, 0, 0, 0 });
}
MockHttpProjectGenerationRequest(String contentType, String fileName, byte[] content) {
MockHttpProjectGenerationRequest(@Nullable String contentType, @Nullable String fileName, byte[] content) {
this.contentType = (contentType != null) ? contentType : "application/text";
this.fileName = fileName;
this.content = content;
@@ -26,6 +26,7 @@ import java.util.zip.ZipOutputStream;
import joptsimple.OptionSet;
import org.apache.hc.core5.http.HttpHost;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
@@ -255,6 +256,7 @@ class InitCommandTests extends AbstractHttpClientMockTests {
this.command.run("-g=org.demo", "-a=acme", "-v=1.2.3-SNAPSHOT", "-n=acme-sample",
"--description=Acme sample project", "--package-name=demo.foo", "-t=ant-project", "--build=grunt",
"--format=web", "-p=war", "-j=1.9", "-l=groovy", "-b=1.2.0.RELEASE", "-d=web,data-jpa");
assertThat(this.handler.lastRequest).isNotNull();
assertThat(this.handler.lastRequest.getGroupId()).isEqualTo("org.demo");
assertThat(this.handler.lastRequest.getArtifactId()).isEqualTo("acme");
assertThat(this.handler.lastRequest.getVersion()).isEqualTo("1.2.3-SNAPSHOT");
@@ -281,6 +283,7 @@ class InitCommandTests extends AbstractHttpClientMockTests {
"--description=Acme sample project", "--packageName=demo.foo", "--type=ant-project", "--build=grunt",
"--format=web", "--packaging=war", "--javaVersion=1.9", "--language=groovy",
"--bootVersion=1.2.0.RELEASE", "--dependencies=web,data-jpa");
assertThat(this.handler.lastRequest).isNotNull();
assertThat(this.handler.lastRequest.getGroupId()).isEqualTo("org.demo");
assertThat(this.handler.lastRequest.getArtifactId()).isEqualTo("acme");
assertThat(this.handler.lastRequest.getVersion()).isEqualTo("1.2.3-SNAPSHOT");
@@ -307,6 +310,7 @@ class InitCommandTests extends AbstractHttpClientMockTests {
"--description=Acme sample project", "--package-name=demo.foo", "--type=ant-project", "--build=grunt",
"--format=web", "--packaging=war", "--java-version=1.9", "--language=groovy",
"--boot-version=1.2.0.RELEASE", "--dependencies=web,data-jpa");
assertThat(this.handler.lastRequest).isNotNull();
assertThat(this.handler.lastRequest.getGroupId()).isEqualTo("org.demo");
assertThat(this.handler.lastRequest.getArtifactId()).isEqualTo("acme");
assertThat(this.handler.lastRequest.getVersion()).isEqualTo("1.2.3-SNAPSHOT");
@@ -344,6 +348,7 @@ class InitCommandTests extends AbstractHttpClientMockTests {
void parseTypeOnly() throws Exception {
this.handler.disableProjectGeneration();
this.command.run("-t=ant-project");
assertThat(this.handler.lastRequest).isNotNull();
assertThat(this.handler.lastRequest.getBuild()).isEqualTo("gradle");
assertThat(this.handler.lastRequest.getFormat()).isEqualTo("project");
assertThat(this.handler.lastRequest.isDetectType()).isFalse();
@@ -354,6 +359,7 @@ class InitCommandTests extends AbstractHttpClientMockTests {
void parseBuildOnly() throws Exception {
this.handler.disableProjectGeneration();
this.command.run("--build=ant");
assertThat(this.handler.lastRequest).isNotNull();
assertThat(this.handler.lastRequest.getBuild()).isEqualTo("ant");
assertThat(this.handler.lastRequest.getFormat()).isEqualTo("project");
assertThat(this.handler.lastRequest.isDetectType()).isTrue();
@@ -364,6 +370,7 @@ class InitCommandTests extends AbstractHttpClientMockTests {
void parseFormatOnly() throws Exception {
this.handler.disableProjectGeneration();
this.command.run("--format=web");
assertThat(this.handler.lastRequest).isNotNull();
assertThat(this.handler.lastRequest.getBuild()).isEqualTo("gradle");
assertThat(this.handler.lastRequest.getFormat()).isEqualTo("web");
assertThat(this.handler.lastRequest.isDetectType()).isTrue();
@@ -374,6 +381,7 @@ class InitCommandTests extends AbstractHttpClientMockTests {
void parseLocation() throws Exception {
this.handler.disableProjectGeneration();
this.command.run("foobar.zip");
assertThat(this.handler.lastRequest).isNotNull();
assertThat(this.handler.lastRequest.getOutput()).isEqualTo("foobar.zip");
}
@@ -381,6 +389,7 @@ class InitCommandTests extends AbstractHttpClientMockTests {
void parseLocationWithSlash() throws Exception {
this.handler.disableProjectGeneration();
this.command.run("foobar/");
assertThat(this.handler.lastRequest).isNotNull();
assertThat(this.handler.lastRequest.getOutput()).isEqualTo("foobar");
assertThat(this.handler.lastRequest.isExtract()).isTrue();
}
@@ -415,7 +424,7 @@ class InitCommandTests extends AbstractHttpClientMockTests {
private boolean disableProjectGeneration;
private ProjectGenerationRequest lastRequest;
private @Nullable ProjectGenerationRequest lastRequest;
TestableInitCommandOptionHandler(InitializrService initializrService) {
super(initializrService);
@@ -60,12 +60,22 @@ class InitializrServiceMetadataTests {
assertThat(metadata.getDependencies()).hasSize(5);
// Security description
assertThat(metadata.getDependency("aop").getName()).isEqualTo("AOP");
assertThat(metadata.getDependency("security").getName()).isEqualTo("Security");
assertThat(metadata.getDependency("security").getDescription()).isEqualTo("Security description");
assertThat(metadata.getDependency("jdbc").getName()).isEqualTo("JDBC");
assertThat(metadata.getDependency("data-jpa").getName()).isEqualTo("JPA");
assertThat(metadata.getDependency("data-mongodb").getName()).isEqualTo("MongoDB");
Dependency aop = metadata.getDependency("aop");
assertThat(aop).isNotNull();
assertThat(aop.getName()).isEqualTo("AOP");
Dependency security = metadata.getDependency("security");
assertThat(security).isNotNull();
assertThat(security.getName()).isEqualTo("Security");
assertThat(security.getDescription()).isEqualTo("Security description");
Dependency jdbc = metadata.getDependency("jdbc");
assertThat(jdbc).isNotNull();
assertThat(jdbc.getName()).isEqualTo("JDBC");
Dependency dataJpa = metadata.getDependency("data-jpa");
assertThat(dataJpa).isNotNull();
assertThat(dataJpa.getName()).isEqualTo("JPA");
Dependency dataMongodb = metadata.getDependency("data-mongodb");
assertThat(dataMongodb).isNotNull();
assertThat(dataMongodb.getName()).isEqualTo("MongoDB");
}
@Test
@@ -19,6 +19,7 @@ package org.springframework.boot.cli.command.init;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpHost;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@@ -140,7 +141,8 @@ class InitializrServiceTests extends AbstractHttpClientMockTests {
return entity;
}
private static void assertProjectEntity(ProjectGenerationResponse entity, String mimeType, String fileName) {
private static void assertProjectEntity(ProjectGenerationResponse entity, @Nullable String mimeType,
@Nullable String fileName) {
if (mimeType == null) {
assertThat(entity.getContentType()).isNull();
}
@@ -23,6 +23,7 @@ import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
import org.springframework.boot.cli.json.JSONException;
@@ -219,7 +220,7 @@ class ProjectGenerationRequestTests {
return createUrl("/starter.zip" + param);
}
void setBuildAndFormat(String build, String format) {
void setBuildAndFormat(@Nullable String build, @Nullable String format) {
this.request.setBuild((build != null) ? build : "maven");
this.request.setFormat((format != null) ? format : "project");
this.request.setDetectType(true);