Refine null-safety in the spring-test module

Closes gh-34161
This commit is contained in:
Sébastien Deleuze
2024-12-26 17:45:17 +01:00
parent 7417bd0ac1
commit a442c180f1
19 changed files with 47 additions and 29 deletions

View File

@@ -410,7 +410,7 @@ public class SqlScriptsTestExecutionListener extends AbstractTestExecutionListen
* Detect a default SQL script by implementing the algorithm defined in
* {@link Sql#scripts}.
*/
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
private String detectDefaultScript(Class<?> testClass, @Nullable Method testMethod, boolean classLevel) {
Assert.state(classLevel || testMethod != null, "Method-level @Sql requires a testMethod");

View File

@@ -373,7 +373,7 @@ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, Tes
* the supplied {@link TestContextManager}.
* @since 6.1
*/
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // org.junit.jupiter.api.extension.ExecutableInvoker is not null marked
private static void registerMethodInvoker(TestContextManager testContextManager, ExtensionContext context) {
testContextManager.getTestContext().setMethodInvoker(context.getExecutableInvoker()::invoke);
}

View File

@@ -84,7 +84,7 @@ public abstract class AbstractDirtiesContextTestExecutionListener extends Abstra
* @since 4.2
* @see #dirtyContext
*/
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
protected void beforeOrAfterTestMethod(TestContext testContext, MethodMode requiredMethodMode,
ClassMode requiredClassMode) throws Exception {
@@ -136,7 +136,7 @@ public abstract class AbstractDirtiesContextTestExecutionListener extends Abstra
* @since 4.2
* @see #dirtyContext
*/
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
protected void beforeOrAfterTestClass(TestContext testContext, ClassMode requiredClassMode) throws Exception {
Assert.notNull(testContext, "TestContext must not be null");
Assert.notNull(requiredClassMode, "requiredClassMode must not be null");

View File

@@ -232,7 +232,7 @@ abstract class ContextLoaderUtils {
* @throws IllegalArgumentException if the supplied class is {@code null} or if
* {@code @ContextConfiguration} is not <em>present</em> on the supplied class
*/
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
static List<ContextConfigurationAttributes> resolveContextConfigurationAttributes(Class<?> testClass) {
Assert.notNull(testClass, "Class must not be null");

View File

@@ -134,7 +134,7 @@ public abstract class TestPropertySourceUtils {
return mergedAttributes;
}
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
private static boolean duplicationDetected(TestPropertySourceAttributes currentAttributes,
@Nullable TestPropertySourceAttributes previousAttributes) {

View File

@@ -194,7 +194,7 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
* @see #getTransactionManager(TestContext, String)
*/
@Override
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public void beforeTestMethod(final TestContext testContext) throws Exception {
Method testMethod = testContext.getTestMethod();
Class<?> testClass = testContext.getTestClass();

View File

@@ -103,7 +103,6 @@ public class MediaTypeAssert extends AbstractObjectAssert<MediaTypeAssert, Media
}
@SuppressWarnings("NullAway")
private MediaType parseMediaType(String value) {
try {
return MediaType.parseMediaType(value);

View File

@@ -489,7 +489,7 @@ public abstract class AbstractJsonContentAssert<SELF extends AbstractJsonContent
return (this.actual != null ? this.actual.getJson() : null);
}
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
private String toNonNullJsonString() {
String jsonString = toJsonString();
Assertions.assertThat(jsonString).as("JSON content").isNotNull();

View File

@@ -173,7 +173,7 @@ public abstract class ReflectionTestUtils {
* @see ReflectionUtils#setField(Field, Object, Object)
* @see AopTestUtils#getUltimateTargetObject(Object)
*/
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public static void setField(@Nullable Object targetObject, @Nullable Class<?> targetClass,
@Nullable String name, @Nullable Object value, @Nullable Class<?> type) {
@@ -258,7 +258,7 @@ public abstract class ReflectionTestUtils {
* @see ReflectionUtils#getField(Field, Object)
* @see AopTestUtils#getUltimateTargetObject(Object)
*/
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public static @Nullable Object getField(@Nullable Object targetObject, @Nullable Class<?> targetClass, String name) {
Assert.isTrue(targetObject != null || targetClass != null,
"Either targetObject or targetClass for the field must be specified");

View File

@@ -109,7 +109,7 @@ public abstract class ModelAndViewAssert {
* @param mav the ModelAndView to test against (never {@code null})
* @param expectedModel the expected model
*/
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public static void assertModelAttributeValues(ModelAndView mav, Map<String, Object> expectedModel) {
Map<String, Object> model = mav.getModel();

View File

@@ -80,22 +80,32 @@ public class UriAssert extends AbstractStringAssert<UriAssert> {
return this;
}
@SuppressWarnings("NullAway")
private String buildUri(String uriTemplate, Object... uriVars) {
try {
return UriComponentsBuilder.fromUriString(uriTemplate)
.buildAndExpand(uriVars).encode().toUriString();
}
catch (Exception ex) {
String message = ex.getMessage();
throw Failures.instance().failure(this.info,
new ShouldBeValidUriTemplate(uriTemplate, ex.getMessage()));
message == null ?
new ShouldBeValidUriTemplate(uriTemplate) :
new ShouldBeValidUriTemplateWithMessage(uriTemplate, message));
}
}
private static final class ShouldBeValidUriTemplate extends BasicErrorMessageFactory {
private ShouldBeValidUriTemplate(String uriTemplate, String errorMessage) {
private ShouldBeValidUriTemplate(String uriTemplate) {
super("%nExpecting:%n %s%nTo be a valid URI template%n", uriTemplate);
}
}
private static final class ShouldBeValidUriTemplateWithMessage extends BasicErrorMessageFactory {
private ShouldBeValidUriTemplateWithMessage(String uriTemplate, String errorMessage) {
super("%nExpecting:%n %s%nTo be a valid URI template but got:%n %s%n", uriTemplate, errorMessage);
}
}

View File

@@ -159,7 +159,7 @@ public abstract class MockRestRequestMatchers {
* @see #queryParam(String, String...)
*/
@SafeVarargs
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public static RequestMatcher queryParam(String name, Matcher<? super String>... matchers) {
return request -> {
MultiValueMap<String, String> params = getQueryParams(request);
@@ -187,7 +187,7 @@ public abstract class MockRestRequestMatchers {
* @see #queryParamList(String, Matcher)
* @see #queryParam(String, Matcher...)
*/
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public static RequestMatcher queryParam(String name, String... expectedValues) {
return request -> {
MultiValueMap<String, String> params = getQueryParams(request);

View File

@@ -62,7 +62,7 @@ class WiretapConnector implements ClientHttpConnector {
@Override
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public Mono<ClientHttpResponse> connect(HttpMethod method, URI uri,
Function<? super ClientHttpRequest, Mono<Void>> requestCallback) {
@@ -180,7 +180,7 @@ class WiretapConnector implements ClientHttpConnector {
return this.publisherNested;
}
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
public Mono<byte[]> getContent() {
return Mono.defer(() -> {
if (this.content.scan(Scannable.Attr.TERMINATED) == Boolean.TRUE) {

View File

@@ -124,13 +124,12 @@ class DefaultMvcResult implements MvcResult {
}
@Override
public Object getAsyncResult() {
public @Nullable Object getAsyncResult() {
return getAsyncResult(-1);
}
@Override
@SuppressWarnings("NullAway")
public Object getAsyncResult(long timeToWait) {
public @Nullable Object getAsyncResult(long timeToWait) {
if (this.mockRequest.getAsyncContext() != null && timeToWait == -1) {
long requestTimeout = this.mockRequest.getAsyncContext().getTimeout();
timeToWait = requestTimeout == -1 ? Long.MAX_VALUE : requestTimeout;

View File

@@ -85,7 +85,7 @@ public interface MvcResult {
* {@link #getAsyncResult(long)} to specify the amount of time to wait.
* @throws IllegalStateException if the async result was not set
*/
Object getAsyncResult();
@Nullable Object getAsyncResult();
/**
* Get the result of async execution and wait if necessary.
@@ -96,6 +96,6 @@ public interface MvcResult {
* MockAsyncContext#setTimeout} for more details.
* @throws IllegalStateException if the async result was not set
*/
Object getAsyncResult(long timeToWait);
@Nullable Object getAsyncResult(long timeToWait);
}

View File

@@ -212,7 +212,7 @@ public class MvcTestResultAssert extends AbstractMockHttpServletResponseAssert<M
return this.actual.getMvcResult().getResolvedException();
}
@SuppressWarnings("NullAway")
@SuppressWarnings("NullAway") // Dataflow analysis limitation
private ModelAndView getModelAndView() {
ModelAndView modelAndView = getMvcResult().getModelAndView();
Assertions.assertThat(modelAndView).as("ModelAndView").isNotNull();

View File

@@ -292,12 +292,12 @@ public class MockMvcHttpConnector implements ClientHttpConnector {
}
@Override
public Object getAsyncResult() {
public @Nullable Object getAsyncResult() {
return this.mvcResult.getAsyncResult();
}
@Override
public Object getAsyncResult(long timeToWait) {
public @Nullable Object getAsyncResult(long timeToWait) {
return this.mvcResult.getAsyncResult(timeToWait);
}