Decorate all Assert implementations with @CheckReturnValue

See gh-46766

Signed-off-by: Stefano Cordio <stefano.cordio@gmail.com>
This commit is contained in:
Stefano Cordio
2025-12-19 10:39:37 +01:00
committed by Stéphane Nicoll
parent 458f7f6ac9
commit b2b0fed285
14 changed files with 164 additions and 10 deletions
@@ -38,6 +38,8 @@ import org.assertj.core.api.AssertProvider;
import org.assertj.core.api.ListAssert; import org.assertj.core.api.ListAssert;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.springframework.lang.CheckReturnValue;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.contentOf; import static org.assertj.core.api.Assertions.contentOf;
@@ -172,6 +174,7 @@ abstract class AbstractArchiveIntegrationTests {
return this; return this;
} }
@CheckReturnValue
ListAssert<String> entryNamesInPath(String path) { ListAssert<String> entryNamesInPath(String path) {
List<String> matches = new ArrayList<>(); List<String> matches = new ArrayList<>();
withJarFile((jarFile) -> withEntries(jarFile, withJarFile((jarFile) -> withEntries(jarFile,
@@ -70,6 +70,7 @@ import org.gradle.api.tasks.VerificationException;
* @author Phillip Webb * @author Phillip Webb
* @author Dmytro Nosan * @author Dmytro Nosan
* @author Moritz Halbritter * @author Moritz Halbritter
* @author Stefano Cordio
*/ */
public abstract class ArchitectureCheck extends DefaultTask { public abstract class ArchitectureCheck extends DefaultTask {
@@ -93,6 +94,8 @@ public abstract class ArchitectureCheck extends DefaultTask {
getRules().addAll(whenMainSources( getRules().addAll(whenMainSources(
() -> ArchitectureRules.configurationPropertiesDeprecation(ArchitectureCheckAnnotation.classFor( () -> ArchitectureRules.configurationPropertiesDeprecation(ArchitectureCheckAnnotation.classFor(
getAnnotationClasses().get(), ArchitectureCheckAnnotation.DEPRECATED_CONFIGURATION_PROPERTY)))); getAnnotationClasses().get(), ArchitectureCheckAnnotation.DEPRECATED_CONFIGURATION_PROPERTY))));
getRules().addAll(whenMainSources(() -> Collections.singletonList(
ArchitectureRules.allCustomAssertionMethodsNotReturningSelfShouldBeAnnotatedWithCheckReturnValue())));
getRules().addAll(and(getNullMarkedEnabled(), isMainSourceSet()).map(whenTrue(() -> Collections.singletonList( getRules().addAll(and(getNullMarkedEnabled(), isMainSourceSet()).map(whenTrue(() -> Collections.singletonList(
ArchitectureRules.packagesShouldBeAnnotatedWithNullMarked(getNullMarkedIgnoredPackages().get()))))); ArchitectureRules.packagesShouldBeAnnotatedWithNullMarked(getNullMarkedIgnoredPackages().get())))));
getRuleDescriptions().set(getRules().map(this::asDescriptions)); getRuleDescriptions().set(getRules().map(this::asDescriptions));
@@ -63,6 +63,7 @@ import com.tngtech.archunit.library.dependencies.SlicesRuleDefinition;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Role; import org.springframework.context.annotation.Role;
import org.springframework.lang.CheckReturnValue;
import org.springframework.util.ResourceUtils; import org.springframework.util.ResourceUtils;
/** /**
@@ -75,6 +76,7 @@ import org.springframework.util.ResourceUtils;
* @author Phillip Webb * @author Phillip Webb
* @author Ngoc Nhan * @author Ngoc Nhan
* @author Moritz Halbritter * @author Moritz Halbritter
* @author Stefano Cordio
*/ */
final class ArchitectureRules { final class ArchitectureRules {
@@ -158,6 +160,26 @@ final class ArchitectureRules {
.allowEmptyShould(true); .allowEmptyShould(true);
} }
static ArchRule allCustomAssertionMethodsNotReturningSelfShouldBeAnnotatedWithCheckReturnValue() {
return ArchRuleDefinition.methods()
.that()
.areDeclaredInClassesThat()
.implement("org.assertj.core.api.Assert")
.and()
.arePublic()
.and()
.doNotHaveModifier(JavaModifier.BRIDGE)
.and(doNotReturnSelfType())
.should()
.beAnnotatedWith(CheckReturnValue.class)
.allowEmptyShould(true);
}
private static DescribedPredicate<JavaMethod> doNotReturnSelfType() {
return DescribedPredicate.describe("do not return self type",
(method) -> !method.getRawReturnType().equals(method.getOwner()));
}
private static ArchRule allPackagesShouldBeFreeOfTangles() { private static ArchRule allPackagesShouldBeFreeOfTangles() {
return SlicesRuleDefinition.slices() return SlicesRuleDefinition.slices()
.matching("(**)") .matching("(**)")
@@ -62,13 +62,18 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Scott Frederick * @author Scott Frederick
* @author Ivan Malutin * @author Ivan Malutin
* @author Dmytro Nosan * @author Dmytro Nosan
* @author Stefano Cordio
*/ */
class ArchitectureCheckTests { class ArchitectureCheckTests {
private static final String SPRING_CONTEXT = "org.springframework:spring-context:6.2.9"; private static final String ASSERTJ_CORE = "org.assertj:assertj-core:3.27.4";
private static final String JUNIT_JUPITER = "org.junit.jupiter:junit-jupiter:5.12.0"; private static final String JUNIT_JUPITER = "org.junit.jupiter:junit-jupiter:5.12.0";
private static final String SPRING_CONTEXT = "org.springframework:spring-context:6.2.9";
private static final String SPRING_CORE = "org.springframework:spring-core:6.2.9";
private static final String SPRING_INTEGRATION_JMX = "org.springframework.integration:spring-integration-jmx:6.5.1"; private static final String SPRING_INTEGRATION_JMX = "org.springframework.integration:spring-integration-jmx:6.5.1";
private GradleBuild gradleBuild; private GradleBuild gradleBuild;
@@ -452,6 +457,23 @@ class ArchitectureCheckTests {
"DeprecatedConfigurationPropertySince.getProperty"); "DeprecatedConfigurationPropertySince.getProperty");
} }
@Test
void whenCustomAssertionMethodNotReturningSelfIsAnnotatedWithCheckReturnValueShouldSucceedAndWriteEmptyReport()
throws IOException {
prepareTask(Task.CHECK_ARCHITECTURE_MAIN, "assertj/checkReturnValue");
build(this.gradleBuild.withDependencies(ASSERTJ_CORE, SPRING_CORE), Task.CHECK_ARCHITECTURE_MAIN);
}
@Test
void whenCustomAssertionMethodNotReturningSelfIsNotAnnotatedWithCheckReturnValueShouldFailAndWriteReport()
throws IOException {
prepareTask(Task.CHECK_ARCHITECTURE_MAIN, "assertj/noCheckReturnValue");
buildAndFail(this.gradleBuild.withDependencies(ASSERTJ_CORE), Task.CHECK_ARCHITECTURE_MAIN,
"methods that are declared in classes that implement org.assertj.core.api.Assert and "
+ "are public and do not have modifier BRIDGE and do not return self type should be annotated "
+ "with @CheckReturnValue");
}
private void prepareTask(Task task, String... sourceDirectories) throws IOException { private void prepareTask(Task task, String... sourceDirectories) throws IOException {
for (String sourceDirectory : sourceDirectories) { for (String sourceDirectory : sourceDirectories) {
FileSystemUtils.copyRecursively( FileSystemUtils.copyRecursively(
@@ -0,0 +1,39 @@
/*
* Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.build.architecture.assertj.checkReturnValue;
import org.assertj.core.api.AbstractAssert;
import org.springframework.lang.CheckReturnValue;
public class WithCheckReturnValue extends AbstractAssert<WithCheckReturnValue, Object> {
WithCheckReturnValue() {
super(null, WithCheckReturnValue.class);
}
@CheckReturnValue
public Object notReturningSelf() {
return new Object();
}
@Override
public WithCheckReturnValue isEqualTo(Object expected) {
return super.isEqualTo(expected);
}
}
@@ -0,0 +1,31 @@
/*
* Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.build.architecture.assertj.noCheckReturnValue;
import org.assertj.core.api.AbstractAssert;
public class NoCheckReturnValue extends AbstractAssert<NoCheckReturnValue, Object> {
NoCheckReturnValue() {
super(null, NoCheckReturnValue.class);
}
public Object notReturningSelf() {
return new Object();
}
}
+3
View File
@@ -6,6 +6,9 @@
<allow pkg="io.micrometer.observation" /> <allow pkg="io.micrometer.observation" />
<disallow pkg="io.micrometer" /> <disallow pkg="io.micrometer" />
<!-- Improve DevEx with fluent APIs -->
<allow class="org.springframework.lang.CheckReturnValue" />
<!-- Use JSpecify for nullability (not Spring) --> <!-- Use JSpecify for nullability (not Spring) -->
<allow class="org.springframework.lang.Contract" /> <allow class="org.springframework.lang.Contract" />
<disallow pkg="org.springframework.lang" /> <disallow pkg="org.springframework.lang" />
@@ -26,7 +26,6 @@ import org.assertj.core.api.AbstractAssert;
import org.assertj.core.api.AbstractObjectArrayAssert; import org.assertj.core.api.AbstractObjectArrayAssert;
import org.assertj.core.api.AbstractObjectAssert; import org.assertj.core.api.AbstractObjectAssert;
import org.assertj.core.api.AbstractThrowableAssert; import org.assertj.core.api.AbstractThrowableAssert;
import org.assertj.core.api.Assertions;
import org.assertj.core.api.MapAssert; import org.assertj.core.api.MapAssert;
import org.assertj.core.error.BasicErrorMessageFactory; import org.assertj.core.error.BasicErrorMessageFactory;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
@@ -37,6 +36,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.lang.CheckReturnValue;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@@ -224,13 +224,14 @@ public class ApplicationContextAssert<C extends ApplicationContext>
* @return array assertions for the bean names * @return array assertions for the bean names
* @throws AssertionError if the application context did not start * @throws AssertionError if the application context did not start
*/ */
@CheckReturnValue
public <T> AbstractObjectArrayAssert<?, String> getBeanNames(Class<T> type) { public <T> AbstractObjectArrayAssert<?, String> getBeanNames(Class<T> type) {
if (this.startupFailure != null) { if (this.startupFailure != null) {
throwAssertionError(contextFailedToStartWhenExpecting(this.startupFailure, throwAssertionError(contextFailedToStartWhenExpecting(this.startupFailure,
"to get beans names with type:%n <%s>", type)); "to get beans names with type:%n <%s>", type));
} }
return Assertions.assertThat(getApplicationContext().getBeanNamesForType(type)) return assertThat(getApplicationContext().getBeanNamesForType(type)).as("Bean names of type <%s> from <%s>",
.as("Bean names of type <%s> from <%s>", type, getApplicationContext()); type, getApplicationContext());
} }
/** /**
@@ -249,6 +250,7 @@ public class ApplicationContextAssert<C extends ApplicationContext>
* @throws AssertionError if the application context contains multiple beans of the * @throws AssertionError if the application context contains multiple beans of the
* given type * given type
*/ */
@CheckReturnValue
public <T> AbstractObjectAssert<?, T> getBean(Class<T> type) { public <T> AbstractObjectAssert<?, T> getBean(Class<T> type) {
return getBean(type, Scope.INCLUDE_ANCESTORS); return getBean(type, Scope.INCLUDE_ANCESTORS);
} }
@@ -270,6 +272,7 @@ public class ApplicationContextAssert<C extends ApplicationContext>
* @throws AssertionError if the application context contains multiple beans of the * @throws AssertionError if the application context contains multiple beans of the
* given type * given type
*/ */
@CheckReturnValue
public <T> AbstractObjectAssert<?, T> getBean(Class<T> type, Scope scope) { public <T> AbstractObjectAssert<?, T> getBean(Class<T> type, Scope scope) {
Assert.notNull(scope, "'scope' must not be null"); Assert.notNull(scope, "'scope' must not be null");
if (this.startupFailure != null) { if (this.startupFailure != null) {
@@ -284,7 +287,7 @@ public class ApplicationContextAssert<C extends ApplicationContext>
getApplicationContext(), type, names)); getApplicationContext(), type, names));
} }
T bean = (name != null) ? getApplicationContext().getBean(name, type) : null; T bean = (name != null) ? getApplicationContext().getBean(name, type) : null;
return Assertions.assertThat(bean).as("Bean of type <%s> from <%s>", type, getApplicationContext()); return assertThat(bean).as("Bean of type <%s> from <%s>", type, getApplicationContext());
} }
private @Nullable String getPrimary(String[] names, Scope scope) { private @Nullable String getPrimary(String[] names, Scope scope) {
@@ -330,13 +333,14 @@ public class ApplicationContextAssert<C extends ApplicationContext>
* is found * is found
* @throws AssertionError if the application context did not start * @throws AssertionError if the application context did not start
*/ */
@CheckReturnValue
public AbstractObjectAssert<?, Object> getBean(String name) { public AbstractObjectAssert<?, Object> getBean(String name) {
if (this.startupFailure != null) { if (this.startupFailure != null) {
throwAssertionError( throwAssertionError(
contextFailedToStartWhenExpecting(this.startupFailure, "to contain a bean of name:%n <%s>", name)); contextFailedToStartWhenExpecting(this.startupFailure, "to contain a bean of name:%n <%s>", name));
} }
Object bean = findBean(name); Object bean = findBean(name);
return Assertions.assertThat(bean).as("Bean of name <%s> from <%s>", name, getApplicationContext()); return assertThat(bean).as("Bean of name <%s> from <%s>", name, getApplicationContext());
} }
/** /**
@@ -357,6 +361,7 @@ public class ApplicationContextAssert<C extends ApplicationContext>
* name but a different type * name but a different type
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@CheckReturnValue
public <T> AbstractObjectAssert<?, T> getBean(String name, Class<T> type) { public <T> AbstractObjectAssert<?, T> getBean(String name, Class<T> type) {
if (this.startupFailure != null) { if (this.startupFailure != null) {
throwAssertionError(contextFailedToStartWhenExpecting(this.startupFailure, throwAssertionError(contextFailedToStartWhenExpecting(this.startupFailure,
@@ -368,8 +373,8 @@ public class ApplicationContextAssert<C extends ApplicationContext>
"%nExpecting:%n <%s>%nto contain a bean of name:%n <%s> (%s)%nbut found:%n <%s> of type <%s>", "%nExpecting:%n <%s>%nto contain a bean of name:%n <%s> (%s)%nbut found:%n <%s> of type <%s>",
getApplicationContext(), name, type, bean, bean.getClass())); getApplicationContext(), name, type, bean, bean.getClass()));
} }
return Assertions.assertThat((T) bean) return assertThat((T) bean).as("Bean of name <%s> and type <%s> from <%s>", name, type,
.as("Bean of name <%s> and type <%s> from <%s>", name, type, getApplicationContext()); getApplicationContext());
} }
private @Nullable Object findBean(String name) { private @Nullable Object findBean(String name) {
@@ -395,6 +400,7 @@ public class ApplicationContextAssert<C extends ApplicationContext>
* no beans are found * no beans are found
* @throws AssertionError if the application context did not start * @throws AssertionError if the application context did not start
*/ */
@CheckReturnValue
public <T> MapAssert<String, T> getBeans(Class<T> type) { public <T> MapAssert<String, T> getBeans(Class<T> type) {
return getBeans(type, Scope.INCLUDE_ANCESTORS); return getBeans(type, Scope.INCLUDE_ANCESTORS);
} }
@@ -414,14 +420,15 @@ public class ApplicationContextAssert<C extends ApplicationContext>
* no beans are found * no beans are found
* @throws AssertionError if the application context did not start * @throws AssertionError if the application context did not start
*/ */
@CheckReturnValue
public <T> MapAssert<String, T> getBeans(Class<T> type, Scope scope) { public <T> MapAssert<String, T> getBeans(Class<T> type, Scope scope) {
Assert.notNull(scope, "'scope' must not be null"); Assert.notNull(scope, "'scope' must not be null");
if (this.startupFailure != null) { if (this.startupFailure != null) {
throwAssertionError( throwAssertionError(
contextFailedToStartWhenExpecting(this.startupFailure, "to get beans of type:%n <%s>", type)); contextFailedToStartWhenExpecting(this.startupFailure, "to get beans of type:%n <%s>", type));
} }
return Assertions.assertThat(scope.getBeansOfType(getApplicationContext(), type)) return assertThat(scope.getBeansOfType(getApplicationContext(), type)).as("Beans of type <%s> from <%s>", type,
.as("Beans of type <%s> from <%s>", type, getApplicationContext()); getApplicationContext());
} }
/** /**
@@ -434,6 +441,7 @@ public class ApplicationContextAssert<C extends ApplicationContext>
* @return assertions on the cause of the failure * @return assertions on the cause of the failure
* @throws AssertionError if the application context started without a failure * @throws AssertionError if the application context started without a failure
*/ */
@CheckReturnValue
public AbstractThrowableAssert<?, ? extends Throwable> getFailure() { public AbstractThrowableAssert<?, ? extends Throwable> getFailure() {
hasFailed(); hasFailed();
return assertThat(this.startupFailure); return assertThat(this.startupFailure);
@@ -40,6 +40,7 @@ import org.skyscreamer.jsonassert.JSONCompareResult;
import org.skyscreamer.jsonassert.comparator.JSONComparator; import org.skyscreamer.jsonassert.comparator.JSONComparator;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.lang.CheckReturnValue;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.util.function.ThrowingFunction; import org.springframework.util.function.ThrowingFunction;
@@ -917,6 +918,7 @@ public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSeq
* @return a new assertion object whose object under test is the extracted item * @return a new assertion object whose object under test is the extracted item
* @throws AssertionError if the path is not valid * @throws AssertionError if the path is not valid
*/ */
@CheckReturnValue
public AbstractObjectAssert<?, Object> extractingJsonPathValue(CharSequence expression, Object... args) { public AbstractObjectAssert<?, Object> extractingJsonPathValue(CharSequence expression, Object... args) {
return Assertions.assertThat(new JsonPathValue(expression, args).getValue(false)); return Assertions.assertThat(new JsonPathValue(expression, args).getValue(false));
} }
@@ -929,6 +931,7 @@ public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSeq
* @return a new assertion object whose object under test is the extracted item * @return a new assertion object whose object under test is the extracted item
* @throws AssertionError if the path is not valid or does not result in a string * @throws AssertionError if the path is not valid or does not result in a string
*/ */
@CheckReturnValue
public AbstractCharSequenceAssert<?, String> extractingJsonPathStringValue(CharSequence expression, public AbstractCharSequenceAssert<?, String> extractingJsonPathStringValue(CharSequence expression,
Object... args) { Object... args) {
return Assertions.assertThat(extractingJsonPathValue(expression, args, String.class, "a string")); return Assertions.assertThat(extractingJsonPathValue(expression, args, String.class, "a string"));
@@ -942,6 +945,7 @@ public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSeq
* @return a new assertion object whose object under test is the extracted item * @return a new assertion object whose object under test is the extracted item
* @throws AssertionError if the path is not valid or does not result in a number * @throws AssertionError if the path is not valid or does not result in a number
*/ */
@CheckReturnValue
public AbstractObjectAssert<?, Number> extractingJsonPathNumberValue(CharSequence expression, Object... args) { public AbstractObjectAssert<?, Number> extractingJsonPathNumberValue(CharSequence expression, Object... args) {
return Assertions.assertThat(extractingJsonPathValue(expression, args, Number.class, "a number")); return Assertions.assertThat(extractingJsonPathValue(expression, args, Number.class, "a number"));
} }
@@ -954,6 +958,7 @@ public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSeq
* @return a new assertion object whose object under test is the extracted item * @return a new assertion object whose object under test is the extracted item
* @throws AssertionError if the path is not valid or does not result in a boolean * @throws AssertionError if the path is not valid or does not result in a boolean
*/ */
@CheckReturnValue
public AbstractBooleanAssert<?> extractingJsonPathBooleanValue(CharSequence expression, Object... args) { public AbstractBooleanAssert<?> extractingJsonPathBooleanValue(CharSequence expression, Object... args) {
return Assertions.assertThat(extractingJsonPathValue(expression, args, Boolean.class, "a boolean")); return Assertions.assertThat(extractingJsonPathValue(expression, args, Boolean.class, "a boolean"));
} }
@@ -968,6 +973,7 @@ public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSeq
* @throws AssertionError if the path is not valid or does not result in an array * @throws AssertionError if the path is not valid or does not result in an array
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@CheckReturnValue
public <E> ListAssert<E> extractingJsonPathArrayValue(CharSequence expression, Object... args) { public <E> ListAssert<E> extractingJsonPathArrayValue(CharSequence expression, Object... args) {
return Assertions.assertThat(extractingJsonPathValue(expression, args, List.class, "an array")); return Assertions.assertThat(extractingJsonPathValue(expression, args, List.class, "an array"));
} }
@@ -983,6 +989,7 @@ public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSeq
* @throws AssertionError if the path is not valid or does not result in a map * @throws AssertionError if the path is not valid or does not result in a map
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@CheckReturnValue
public <K, V> MapAssert<K, V> extractingJsonPathMapValue(CharSequence expression, Object... args) { public <K, V> MapAssert<K, V> extractingJsonPathMapValue(CharSequence expression, Object... args) {
return Assertions.assertThat(extractingJsonPathValue(expression, args, Map.class, "a map")); return Assertions.assertThat(extractingJsonPathValue(expression, args, Map.class, "a map"));
} }
@@ -22,6 +22,8 @@ import org.assertj.core.api.AbstractObjectAssert;
import org.assertj.core.api.Assert; import org.assertj.core.api.Assert;
import org.assertj.core.api.InstanceOfAssertFactories; import org.assertj.core.api.InstanceOfAssertFactories;
import org.springframework.lang.CheckReturnValue;
/** /**
* AssertJ {@link Assert} for {@link ObjectContent}. * AssertJ {@link Assert} for {@link ObjectContent}.
* *
@@ -41,6 +43,7 @@ public class ObjectContentAssert<A> extends AbstractObjectAssert<ObjectContentAs
* allow chaining of array-specific assertions from this call. * allow chaining of array-specific assertions from this call.
* @return an array assertion object * @return an array assertion object
*/ */
@CheckReturnValue
public AbstractObjectArrayAssert<?, Object> asArray() { public AbstractObjectArrayAssert<?, Object> asArray() {
return asInstanceOf(InstanceOfAssertFactories.ARRAY); return asInstanceOf(InstanceOfAssertFactories.ARRAY);
} }
@@ -50,6 +53,7 @@ public class ObjectContentAssert<A> extends AbstractObjectAssert<ObjectContentAs
* chaining of map-specific assertions from this call. * chaining of map-specific assertions from this call.
* @return a map assertion object * @return a map assertion object
*/ */
@CheckReturnValue
public AbstractMapAssert<?, ?, Object, Object> asMap() { public AbstractMapAssert<?, ?, Object, Object> asMap() {
return asInstanceOf(InstanceOfAssertFactories.MAP); return asInstanceOf(InstanceOfAssertFactories.MAP);
} }
@@ -32,6 +32,7 @@ import org.assertj.core.api.ListAssert;
import org.assertj.core.api.ObjectAssert; import org.assertj.core.api.ObjectAssert;
import org.springframework.boot.test.json.JsonContentAssert; import org.springframework.boot.test.json.JsonContentAssert;
import org.springframework.lang.CheckReturnValue;
/** /**
* AssertJ {@link org.assertj.core.api.Assert} for Docker image container configuration. * AssertJ {@link org.assertj.core.api.Assert} for Docker image container configuration.
@@ -99,10 +100,12 @@ public class ContainerConfigAssert extends AbstractAssert<ContainerConfigAssert,
super(jsonContentAssert, BuildMetadataAssert.class); super(jsonContentAssert, BuildMetadataAssert.class);
} }
@CheckReturnValue
public ListAssert<Object> buildpacks() { public ListAssert<Object> buildpacks() {
return this.actual.extractingJsonPathArrayValue("$.buildpacks[*].id"); return this.actual.extractingJsonPathArrayValue("$.buildpacks[*].id");
} }
@CheckReturnValue
public AbstractListAssert<?, List<? extends String>, String, ObjectAssert<String>> processOfType(String type) { public AbstractListAssert<?, List<? extends String>, String, ObjectAssert<String>> processOfType(String type) {
return this.actual.extractingJsonPathArrayValue("$.processes[?(@.type=='%s')]", type) return this.actual.extractingJsonPathArrayValue("$.processes[?(@.type=='%s')]", type)
.singleElement() .singleElement()
@@ -132,14 +135,17 @@ public class ContainerConfigAssert extends AbstractAssert<ContainerConfigAssert,
super(jsonContentAssert, LifecycleMetadataAssert.class); super(jsonContentAssert, LifecycleMetadataAssert.class);
} }
@CheckReturnValue
public ListAssert<Object> buildpackLayers(String buildpackId) { public ListAssert<Object> buildpackLayers(String buildpackId) {
return this.actual.extractingJsonPathArrayValue("$.buildpacks[?(@.key=='%s')].layers", buildpackId); return this.actual.extractingJsonPathArrayValue("$.buildpacks[?(@.key=='%s')].layers", buildpackId);
} }
@CheckReturnValue
public AbstractListAssert<?, List<?>, Object, ObjectAssert<Object>> appLayerShas() { public AbstractListAssert<?, List<?>, Object, ObjectAssert<Object>> appLayerShas() {
return this.actual.extractingJsonPathArrayValue("$.app").extracting("sha"); return this.actual.extractingJsonPathArrayValue("$.app").extracting("sha");
} }
@CheckReturnValue
public AbstractObjectAssert<?, Object> sbomLayerSha() { public AbstractObjectAssert<?, Object> sbomLayerSha() {
return this.actual.extractingJsonPathValue("$.sbom.sha"); return this.actual.extractingJsonPathValue("$.sbom.sha");
} }
@@ -34,6 +34,7 @@ import org.springframework.boot.buildpack.platform.docker.DockerApi;
import org.springframework.boot.buildpack.platform.docker.type.ImageReference; import org.springframework.boot.buildpack.platform.docker.type.ImageReference;
import org.springframework.boot.buildpack.platform.docker.type.Layer; import org.springframework.boot.buildpack.platform.docker.type.Layer;
import org.springframework.boot.test.json.JsonContentAssert; import org.springframework.boot.test.json.JsonContentAssert;
import org.springframework.lang.CheckReturnValue;
import org.springframework.util.StreamUtils; import org.springframework.util.StreamUtils;
/** /**
@@ -73,6 +74,7 @@ public class ImageAssert extends AbstractAssert<ImageAssert, ImageReference> {
super(layer, LayerContentAssert.class); super(layer, LayerContentAssert.class);
} }
@CheckReturnValue
public ListAssert<String> entries() { public ListAssert<String> entries() {
List<String> entryNames = new ArrayList<>(); List<String> entryNames = new ArrayList<>();
try { try {
@@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
import org.assertj.core.api.AbstractAssert; import org.assertj.core.api.AbstractAssert;
import org.assertj.core.api.Assert; import org.assertj.core.api.Assert;
import org.springframework.lang.CheckReturnValue;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
@@ -85,6 +86,7 @@ public final class ScheduledExecutorServiceAssert
* @param actual the {@link ScheduledExecutorService} * @param actual the {@link ScheduledExecutorService}
* @return the assertion instance * @return the assertion instance
*/ */
@CheckReturnValue
public static ScheduledExecutorServiceAssert assertThat(ScheduledExecutorService actual) { public static ScheduledExecutorServiceAssert assertThat(ScheduledExecutorService actual) {
return new ScheduledExecutorServiceAssert(actual); return new ScheduledExecutorServiceAssert(actual);
} }
@@ -22,6 +22,7 @@ import org.assertj.core.api.AbstractAssert;
import org.assertj.core.api.Assert; import org.assertj.core.api.Assert;
import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.lang.CheckReturnValue;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
@@ -77,6 +78,7 @@ public final class SimpleAsyncTaskExecutorAssert
* @param actual the {@link SimpleAsyncTaskExecutor} * @param actual the {@link SimpleAsyncTaskExecutor}
* @return the assertion instance * @return the assertion instance
*/ */
@CheckReturnValue
public static SimpleAsyncTaskExecutorAssert assertThat(SimpleAsyncTaskExecutor actual) { public static SimpleAsyncTaskExecutorAssert assertThat(SimpleAsyncTaskExecutor actual) {
return new SimpleAsyncTaskExecutorAssert(actual); return new SimpleAsyncTaskExecutorAssert(actual);
} }