Class SoftAssertionsExtension
- java.lang.Object
-
- org.assertj.core.api.junit.jupiter.SoftAssertionsExtension
-
- All Implemented Interfaces:
org.junit.jupiter.api.extension.AfterTestExecutionCallback
,org.junit.jupiter.api.extension.BeforeEachCallback
,org.junit.jupiter.api.extension.Extension
,org.junit.jupiter.api.extension.ParameterResolver
,org.junit.jupiter.api.extension.TestInstancePostProcessor
public class SoftAssertionsExtension extends Object implements org.junit.jupiter.api.extension.TestInstancePostProcessor, org.junit.jupiter.api.extension.BeforeEachCallback, org.junit.jupiter.api.extension.ParameterResolver, org.junit.jupiter.api.extension.AfterTestExecutionCallback
Extension for JUnit Jupiter that provides support for injecting a concrete implementation ofSoftAssertionsProvider
into test methods and (since 3.18.0) into test fields annotated with@InjectSoftAssertions
.Two examples of
SoftAssertionsProvider
s that come packaged with AssertJ areSoftAssertions
andBDDSoftAssertions
, but custom implementations are also supported as long as they are non-abstract and have a default constructor.Applicability
In this context, the term "test method" refers to any method annotated with
@Test
,@RepeatedTest
,@ParameterizedTest
,@TestFactory
, or@TestTemplate
.
This extension does not injectSoftAssertionsProvider
arguments into test constructors or lifecycle methods.Scope
AnnotatedSoftAssertionsProvider
fields become valid from the `@BeforeEach` lifecycle phase. For parameters, they become are valid when the parameter is resolved.
In theafterTestExecution
phase (immediately after the test has returned, but before theAfterEach
phase, all collected errors (if any) will wrapped in a single multiple-failures error.
AllSoftAssertionsProvider
instances (fields & parameters) created within the scope of the same test method (including itsBeforeEach
phase) will share the same state object to collect the failed assertions, so that all assertion failures from allSoftAssertionsProvider
s will be reported in the order that they failed.Integration with third-party extensions
Sometimes a third-party extension may wish to softly assert something as part of the main test. Or sometimes a third-party extension may be a wrapper around another assertion library (eg, Mockito) and it would be nice for that library's soft assertions to mix well with AssertJ's. This can be achieved through the use of theSoftAssertionExtension
's API. CallinggetAssertionErrorCollector(ExtensionContext)
will return a handle to the error collector used for the current context into which a third-party extension can directly store its assertion failures. Alternatively, callinggetSoftAssertionsProvider()
will instantiate aSoftAssertionsProvider
for the given context that can then be used to make assertions.Examples
Example parameter injection
@ExtendWith(SoftAssertionsExtension.class) class ExampleTestCase { @InjectSoftAssertions BDDSoftAssertions bdd; @Test void multipleFailures(SoftAssertions softly) { softly.assertThat(2 * 3).isEqualTo(0); softly.assertThat(Arrays.asList(1, 2)).containsOnly(1); softly.assertThat(1 + 1).isEqualTo(2); } }
Example field injection
@ExtendWith(SoftlyExtension.class) public class SoftlyExtensionExample { // initialized by the SoftlyExtension extension @InjectSoftAssertions private SoftAssertions soft; @Test public void chained_soft_assertions_example() { String name = "Michael Jordan - Bulls"; soft.assertThat(name) .startsWith("Mi") .contains("Bulls"); // no need to call softly.assertAll(), this is done by the extension } // nested classes test work too @Nested class NestedExample { @Test public void football_assertions_example() { String kylian = "Kylian Mbappé"; soft.assertThat(kylian) .startsWith("Ky") .contains("bap"); // no need to call softly.assertAll(), this is done by the extension } } }
Example using a mix of field and parameter injection
@ExtendWith(SoftAssertionsExtension.class) class ExampleTestCase { @InjectSoftAssertions SoftAssertions softly @Test void multipleFailures(BDDSoftAssertions bdd) { bdd.then(2 * 3).isEqualTo(0); softly.assertThat(Arrays.asList(1, 2)).containsOnly(1); bdd.then(1 + 1).isEqualTo(2); // When SoftAssertionsExtension calls assertAll(), the three // above failures above will be reported in-order. } }
Example third-party extension using
SoftAssertionsExtension
class ExampleTestCase implements BeforeEachCallback { @Override public void beforeEach(ExtensionContext context) { SoftAssertions softly = SoftAssertionsExtension .getSoftAssertionsProvider(context, SoftAssertions.class); softly.assertThat(false).isTrue(); // When SoftAssertionsExtension calls assertAll(), the // above failure will be included in the list of reported failures. } }
- Since:
- 3.13
- Author:
- Sam Brannen, Arthur Mita (author of
SoftlyExtension
), Fr Jeremy Krieg
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description (package private) static class
SoftAssertionsExtension.ThreadLocalErrorCollector
-
Field Summary
Fields Modifier and Type Field Description private static org.junit.jupiter.api.extension.ExtensionContext.Namespace
SOFT_ASSERTIONS_EXTENSION_NAMESPACE
-
Constructor Summary
Constructors Constructor Description SoftAssertionsExtension()
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description void
afterTestExecution(org.junit.jupiter.api.extension.ExtensionContext extensionContext)
private static Class<? extends SoftAssertionsProvider>
asSoftAssertionsProviderClass(Field softAssertionsField, Class<?> providerClass)
void
beforeEach(org.junit.jupiter.api.extension.ExtensionContext context)
private static void
checkHasDefaultConstructor(Field softAssertionsField, Class<? extends SoftAssertionsProvider> softAssertionsProviderClass)
private static void
checkIsNotAbstract(Field softAssertionsField, Class<? extends SoftAssertionsProvider> softAssertionsProviderClass)
private static void
checkIsNotStaticOrFinal(Field softAssertionsField)
static AssertionErrorCollector
getAssertionErrorCollector(org.junit.jupiter.api.extension.ExtensionContext context)
Returns theAssertionErrorCollector
for the given extension context, if none exists for the current context then one is created.static <T extends SoftAssertionsProvider>
TgetSoftAssertionsProvider(org.junit.jupiter.api.extension.ExtensionContext context, Class<T> concreteSoftAssertionsProviderType)
Returns aSoftAssertionsProvider
instance of the given type for the given extension context.private static Collection<SoftAssertionsProvider>
getSoftAssertionsProviders(org.junit.jupiter.api.extension.ExtensionContext context)
private static org.junit.jupiter.api.extension.ExtensionContext.Store
getStore(org.junit.jupiter.api.extension.ExtensionContext extensionContext)
private static SoftAssertionsExtension.ThreadLocalErrorCollector
getThreadLocalCollector(org.junit.jupiter.api.extension.ExtensionContext context)
private static boolean
initialiseDelegate(org.junit.jupiter.api.extension.ExtensionContext context, AssertionErrorCollector collector)
private static <T extends SoftAssertionsProvider>
TinstantiateProvider(org.junit.jupiter.api.extension.ExtensionContext context, Class<T> providerType)
(package private) static boolean
isAnnotatedConcurrent(org.junit.jupiter.api.extension.ExtensionContext context)
(package private) static boolean
isPerClass(org.junit.jupiter.api.extension.ExtensionContext context)
(package private) static boolean
isPerClassConcurrent(org.junit.jupiter.api.extension.ExtensionContext context)
private static boolean
isUnsupportedParameterType(Parameter parameter)
void
postProcessTestInstance(Object testInstance, org.junit.jupiter.api.extension.ExtensionContext context)
Object
resolveParameter(org.junit.jupiter.api.extension.ParameterContext parameterContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext)
private static void
setTestInstanceSoftAssertionsField(Object testInstance, Field softAssertionsField, SoftAssertionsProvider softAssertions)
boolean
supportsParameter(org.junit.jupiter.api.extension.ParameterContext parameterContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext)
-
-
-
Method Detail
-
isPerClass
static boolean isPerClass(org.junit.jupiter.api.extension.ExtensionContext context)
-
isAnnotatedConcurrent
static boolean isAnnotatedConcurrent(org.junit.jupiter.api.extension.ExtensionContext context)
-
isPerClassConcurrent
static boolean isPerClassConcurrent(org.junit.jupiter.api.extension.ExtensionContext context)
-
postProcessTestInstance
public void postProcessTestInstance(Object testInstance, org.junit.jupiter.api.extension.ExtensionContext context) throws Exception
- Specified by:
postProcessTestInstance
in interfaceorg.junit.jupiter.api.extension.TestInstancePostProcessor
- Throws:
Exception
-
beforeEach
public void beforeEach(org.junit.jupiter.api.extension.ExtensionContext context) throws Exception
- Specified by:
beforeEach
in interfaceorg.junit.jupiter.api.extension.BeforeEachCallback
- Throws:
Exception
-
initialiseDelegate
private static boolean initialiseDelegate(org.junit.jupiter.api.extension.ExtensionContext context, AssertionErrorCollector collector)
-
supportsParameter
public boolean supportsParameter(org.junit.jupiter.api.extension.ParameterContext parameterContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext)
- Specified by:
supportsParameter
in interfaceorg.junit.jupiter.api.extension.ParameterResolver
-
resolveParameter
public Object resolveParameter(org.junit.jupiter.api.extension.ParameterContext parameterContext, org.junit.jupiter.api.extension.ExtensionContext extensionContext)
- Specified by:
resolveParameter
in interfaceorg.junit.jupiter.api.extension.ParameterResolver
-
afterTestExecution
public void afterTestExecution(org.junit.jupiter.api.extension.ExtensionContext extensionContext)
- Specified by:
afterTestExecution
in interfaceorg.junit.jupiter.api.extension.AfterTestExecutionCallback
-
isUnsupportedParameterType
private static boolean isUnsupportedParameterType(Parameter parameter)
-
getStore
private static org.junit.jupiter.api.extension.ExtensionContext.Store getStore(org.junit.jupiter.api.extension.ExtensionContext extensionContext)
-
getThreadLocalCollector
private static SoftAssertionsExtension.ThreadLocalErrorCollector getThreadLocalCollector(org.junit.jupiter.api.extension.ExtensionContext context)
-
getAssertionErrorCollector
public static AssertionErrorCollector getAssertionErrorCollector(org.junit.jupiter.api.extension.ExtensionContext context)
Returns theAssertionErrorCollector
for the given extension context, if none exists for the current context then one is created.This method is thread safe - all extensions attempting to access the
AssertionErrorCollector
for a given context through this method will get a reference to the sameAssertionErrorCollector
instance, regardless of the order in which they are called.Third-party extensions that wish to provide soft-asserting behavior can use this method to obtain the current
AssertionErrorCollector
instance and record their assertion failures into it by callingcollectAssertionError(AssertionError)
.
In this way their soft assertions will integrate with the existing AssertJ soft assertions and the assertion failures (both AssertJ's and the third-party extension's) will be reported in the order that they occurred.- Parameters:
context
- theExtensionContext
whose error collector we are attempting to retrieve.- Returns:
- The
AssertionErrorCollector
for the given context.
-
getSoftAssertionsProviders
private static Collection<SoftAssertionsProvider> getSoftAssertionsProviders(org.junit.jupiter.api.extension.ExtensionContext context)
-
instantiateProvider
private static <T extends SoftAssertionsProvider> T instantiateProvider(org.junit.jupiter.api.extension.ExtensionContext context, Class<T> providerType)
-
getSoftAssertionsProvider
public static <T extends SoftAssertionsProvider> T getSoftAssertionsProvider(org.junit.jupiter.api.extension.ExtensionContext context, Class<T> concreteSoftAssertionsProviderType)
Returns aSoftAssertionsProvider
instance of the given type for the given extension context. If no instance of the given type exists for the supplied context, then one is created.
Note that the given type must be a concrete type with an accessible no-arg constructor for this method to work.This method is thread safe - all extensions attempting to access the
SoftAssertionsProvider
for a given context through this method will receive end up getting a reference to the sameSoftAssertionsProvider
instance of that same type, regardless of the order in which they are called.Third party extensions that wish to use soft assertions in their own implementation can use this to get a
SoftAssertionsProvider
instance that interoperates with other soft-asserting extensions (includingSoftAssertionsExtension
).The
SoftAssertionExtension
will take care of initialising this provider instance's delegate at the appropriate time, so that collected soft assertions are routed to theAssertionErrorCollector
instance for the current context.public class CustomExtension implements BeforeEachCallback { @Override public void beforeEach(ExtensionContext context) { CustomSoftAssertions softly = SoftAssertionsExtension.getSoftAssertionsProvider(context, CustomSoftAssertions.class); softly.assertThat(1).isOne(); } }
- Type Parameters:
T
- the type ofSoftAssertionsProvider
to instantiate.- Parameters:
context
- theExtensionContext
whose error collector we are attempting to retrieve.concreteSoftAssertionsProviderType
- the class instance for the type of soft assertions- Returns:
- The
AssertionErrorCollector
for the given context.
-
setTestInstanceSoftAssertionsField
private static void setTestInstanceSoftAssertionsField(Object testInstance, Field softAssertionsField, SoftAssertionsProvider softAssertions)
-
checkHasDefaultConstructor
private static void checkHasDefaultConstructor(Field softAssertionsField, Class<? extends SoftAssertionsProvider> softAssertionsProviderClass)
-
checkIsNotAbstract
private static void checkIsNotAbstract(Field softAssertionsField, Class<? extends SoftAssertionsProvider> softAssertionsProviderClass)
-
asSoftAssertionsProviderClass
private static Class<? extends SoftAssertionsProvider> asSoftAssertionsProviderClass(Field softAssertionsField, Class<?> providerClass)
-
checkIsNotStaticOrFinal
private static void checkIsNotStaticOrFinal(Field softAssertionsField)
-
-