Browse Source

Refine null-safety in the spring-test module

Closes gh-34161
pull/34171/head
Sébastien Deleuze 1 year ago
parent
commit
a442c180f1
  1. 2
      spring-test/src/main/java/org/springframework/test/context/jdbc/SqlScriptsTestExecutionListener.java
  2. 2
      spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtension.java
  3. 4
      spring-test/src/main/java/org/springframework/test/context/support/AbstractDirtiesContextTestExecutionListener.java
  4. 2
      spring-test/src/main/java/org/springframework/test/context/support/ContextLoaderUtils.java
  5. 2
      spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceUtils.java
  6. 2
      spring-test/src/main/java/org/springframework/test/context/transaction/TransactionalTestExecutionListener.java
  7. 1
      spring-test/src/main/java/org/springframework/test/http/MediaTypeAssert.java
  8. 2
      spring-test/src/main/java/org/springframework/test/json/AbstractJsonContentAssert.java
  9. 4
      spring-test/src/main/java/org/springframework/test/util/ReflectionTestUtils.java
  10. 2
      spring-test/src/main/java/org/springframework/test/web/ModelAndViewAssert.java
  11. 16
      spring-test/src/main/java/org/springframework/test/web/UriAssert.java
  12. 4
      spring-test/src/main/java/org/springframework/test/web/client/match/MockRestRequestMatchers.java
  13. 4
      spring-test/src/main/java/org/springframework/test/web/reactive/server/WiretapConnector.java
  14. 5
      spring-test/src/main/java/org/springframework/test/web/servlet/DefaultMvcResult.java
  15. 4
      spring-test/src/main/java/org/springframework/test/web/servlet/MvcResult.java
  16. 2
      spring-test/src/main/java/org/springframework/test/web/servlet/assertj/MvcTestResultAssert.java
  17. 4
      spring-test/src/main/java/org/springframework/test/web/servlet/client/MockMvcHttpConnector.java
  18. 6
      spring-test/src/test/java/org/springframework/test/web/servlet/StubMvcResult.java
  19. 8
      spring-web/src/main/java/org/springframework/http/InvalidMediaTypeException.java

2
spring-test/src/main/java/org/springframework/test/context/jdbc/SqlScriptsTestExecutionListener.java

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

2
spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtension.java

@ -373,7 +373,7 @@ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, Tes
* the supplied {@link TestContextManager}. * the supplied {@link TestContextManager}.
* @since 6.1 * @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) { private static void registerMethodInvoker(TestContextManager testContextManager, ExtensionContext context) {
testContextManager.getTestContext().setMethodInvoker(context.getExecutableInvoker()::invoke); testContextManager.getTestContext().setMethodInvoker(context.getExecutableInvoker()::invoke);
} }

4
spring-test/src/main/java/org/springframework/test/context/support/AbstractDirtiesContextTestExecutionListener.java

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

2
spring-test/src/main/java/org/springframework/test/context/support/ContextLoaderUtils.java

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

2
spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceUtils.java

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

2
spring-test/src/main/java/org/springframework/test/context/transaction/TransactionalTestExecutionListener.java

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

1
spring-test/src/main/java/org/springframework/test/http/MediaTypeAssert.java

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

2
spring-test/src/main/java/org/springframework/test/json/AbstractJsonContentAssert.java

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

4
spring-test/src/main/java/org/springframework/test/util/ReflectionTestUtils.java

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

2
spring-test/src/main/java/org/springframework/test/web/ModelAndViewAssert.java

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

16
spring-test/src/main/java/org/springframework/test/web/UriAssert.java

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

4
spring-test/src/main/java/org/springframework/test/web/client/match/MockRestRequestMatchers.java

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

4
spring-test/src/main/java/org/springframework/test/web/reactive/server/WiretapConnector.java

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

5
spring-test/src/main/java/org/springframework/test/web/servlet/DefaultMvcResult.java

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

4
spring-test/src/main/java/org/springframework/test/web/servlet/MvcResult.java

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

2
spring-test/src/main/java/org/springframework/test/web/servlet/assertj/MvcTestResultAssert.java

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

4
spring-test/src/main/java/org/springframework/test/web/servlet/client/MockMvcHttpConnector.java

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

6
spring-test/src/test/java/org/springframework/test/web/servlet/StubMvcResult.java

@ -16,6 +16,8 @@
package org.springframework.test.web.servlet; package org.springframework.test.web.servlet;
import org.jspecify.annotations.Nullable;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.servlet.FlashMap; import org.springframework.web.servlet.FlashMap;
@ -127,12 +129,12 @@ public class StubMvcResult implements MvcResult {
} }
@Override @Override
public Object getAsyncResult() { public @Nullable Object getAsyncResult() {
return null; return null;
} }
@Override @Override
public Object getAsyncResult(long timeToWait) { public @Nullable Object getAsyncResult(long timeToWait) {
return null; return null;
} }

8
spring-web/src/main/java/org/springframework/http/InvalidMediaTypeException.java

@ -51,6 +51,14 @@ public class InvalidMediaTypeException extends IllegalArgumentException {
this.mediaType = ex.getMimeType(); this.mediaType = ex.getMimeType();
} }
/**
* Returns the detail message string of this exception instance (never {@code null}).
*/
@Override
@SuppressWarnings("NullAway") // InvalidMediaTypeException message is never null
public String getMessage() {
return super.getMessage();
}
/** /**
* Return the offending media type. * Return the offending media type.

Loading…
Cancel
Save