Class 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 of SoftAssertionsProvider into test methods and (since 3.18.0) into test fields annotated with @InjectSoftAssertions.

    Two examples of SoftAssertionsProviders that come packaged with AssertJ are SoftAssertions and BDDSoftAssertions, 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 inject SoftAssertionsProvider arguments into test constructors or lifecycle methods.

    Scope

    Annotated SoftAssertionsProvider fields become valid from the `@BeforeEach` lifecycle phase. For parameters, they become are valid when the parameter is resolved.
    In the afterTestExecution phase (immediately after the test has returned, but before the AfterEach phase, all collected errors (if any) will wrapped in a single multiple-failures error.
    All SoftAssertionsProvider instances (fields & parameters) created within the scope of the same test method (including its BeforeEach phase) will share the same state object to collect the failed assertions, so that all assertion failures from all SoftAssertionsProviders 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 the SoftAssertionExtension's API. Calling getAssertionErrorCollector(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, calling getSoftAssertionsProvider() will instantiate a SoftAssertionsProvider 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
    • Field Detail

      • SOFT_ASSERTIONS_EXTENSION_NAMESPACE

        private static final org.junit.jupiter.api.extension.ExtensionContext.Namespace SOFT_ASSERTIONS_EXTENSION_NAMESPACE
    • Constructor Detail

      • SoftAssertionsExtension

        public SoftAssertionsExtension()
    • 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 interface org.junit.jupiter.api.extension.TestInstancePostProcessor
        Throws:
        Exception
      • beforeEach

        public void beforeEach​(org.junit.jupiter.api.extension.ExtensionContext context)
                        throws Exception
        Specified by:
        beforeEach in interface org.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 interface org.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 interface org.junit.jupiter.api.extension.ParameterResolver
      • afterTestExecution

        public void afterTestExecution​(org.junit.jupiter.api.extension.ExtensionContext extensionContext)
        Specified by:
        afterTestExecution in interface org.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)
      • getAssertionErrorCollector

        public static AssertionErrorCollector getAssertionErrorCollector​(org.junit.jupiter.api.extension.ExtensionContext context)
        Returns the AssertionErrorCollector 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 same AssertionErrorCollector 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 calling collectAssertionError(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 - the ExtensionContext 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 a SoftAssertionsProvider 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 same SoftAssertionsProvider 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 (including SoftAssertionsExtension).

        The SoftAssertionExtension will take care of initialising this provider instance's delegate at the appropriate time, so that collected soft assertions are routed to the AssertionErrorCollector 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 of SoftAssertionsProvider to instantiate.
        Parameters:
        context - the ExtensionContext 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)
      • checkIsNotStaticOrFinal

        private static void checkIsNotStaticOrFinal​(Field softAssertionsField)