Class RecursiveAssertionAssert

All Implemented Interfaces:
Assert<RecursiveAssertionAssert,Object>, Descriptable<RecursiveAssertionAssert>, ExtensionPoints<RecursiveAssertionAssert,Object>

public class RecursiveAssertionAssert extends AbstractAssert<RecursiveAssertionAssert,Object>

An assertion that supports asserting a Predicate over all the fields of an object graph. Cycle avoidance is used, so a graph that has cyclic references is essentially reduced to a tree by this class (the actual object graph is not changed of course, it is treated as an immutable value).

Since:
3.24.0
  • Constructor Details

    • RecursiveAssertionAssert

      public RecursiveAssertionAssert(Object o, org.assertj.core.api.recursive.assertion.RecursiveAssertionConfiguration recursiveAssertionConfiguration)
  • Method Details

    • allFieldsSatisfy

      public RecursiveAssertionAssert allFieldsSatisfy(Predicate<Object> predicate)

      Asserts that the given predicate is met for all fields of the object under test recursively (but not the object itself).

      For example if the object under test is an instance of class A, A has a B field and B a C field then the assertion checks A's B field and B's C field and all C's fields.

      The recursive algorithm employs cycle detection, so object graphs with cyclic references can safely be asserted over without causing looping.

      This method enables recursive asserting using default configuration, which means all fields of all objects have the Predicate applied to them (including primitive fields), no fields are excluded, but:

      • The recursion does not enter into Java Class Library types (java.*, javax.*)
      • The Predicate is applied to Collection and array elements (but not the collection/array itself)
      • The Predicate is applied to Map values but not the map itself or its keys
      • The Predicate is applied to Optional and primitive optional values

      You can change how the recursive assertion deals with arrays, collections, maps and optionals, see:

      It is possible to assert several predicates over the object graph in a row.

      The classes used in recursive asserting are not thread safe. Care must be taken when running tests in parallel not to run assertions over object graphs that are being shared between tests.

      Example:

       class Author {
         String name;
         String email;
         List<Book> books = new ArrayList<>();
      
         Author(String name, String email) {
           this.name = name;
           this.email = email;
         }
       }
      
       class Book {
         String title;
         Author[] authors;
      
         Book(String title, Author[] authors) {
           this.title = title;
           this.authors = authors;
         }
       }
      
       Author pramodSadalage = new Author("Pramod Sadalage", "[email protected]");
       Author martinFowler = new Author("Martin Fowler", "[email protected]");
       Author kentBeck = new Author("Kent Beck", "[email protected]");
      
       Book noSqlDistilled = new Book("NoSql Distilled", new Author[] {pramodSadalage, martinFowler});
       pramodSadalage.books.add(noSqlDistilled);
       martinFowler.books.add(noSqlDistilled);
       
       Book refactoring = new Book("Refactoring", new Author[] {martinFowler, kentBeck});
       martinFowler.books.add(refactoring);
       kentBeck.books.add(refactoring);
      
       // assertion succeeds
       assertThat(pramodSadalage).usingRecursiveAssertion()
                                 .allFieldsSatisfy(field -> field != null); 
      Parameters:
      predicate - The predicate that is recursively applied to all the fields in the object tree of which actual is the root.
      Returns:
      this assertions object
      Throws:
      AssertionError - if one or more fields as described above fail the predicate test.
    • hasNoNullFields

      public RecursiveAssertionAssert hasNoNullFields()
      Asserts that none of the fields of the object under test graph (i.e. recursively getting the fields) are null (but not the object itself).

      This is a convenience method for a common test, and it is equivalent to allFieldsSatisfy(field -> field != null).

      Example:

       class Author {
         String name;
         String email;
         List<Book> books = new ArrayList<>();
      
         Author(String name, String email) {
           this.name = name;
           this.email = email;
         }
       }
      
       class Book {
         String title;
         Author[] authors;
      
         Book(String title, Author[] authors) {
           this.title = title;
           this.authors = authors;
         }
       }
      
       Author pramodSadalage = new Author("Pramod Sadalage", "[email protected]");
       Author martinFowler = new Author("Martin Fowler", "[email protected]");
       Author kentBeck = new Author("Kent Beck", "[email protected]");
      
       Book noSqlDistilled = new Book("NoSql Distilled", new Author[]{pramodSadalage, martinFowler});
       pramodSadalage.books.add(noSqlDistilled);
       martinFowler.books.add(noSqlDistilled);
       
       Book refactoring = new Book("Refactoring", new Author[] {martinFowler, kentBeck});
       martinFowler.books.add(refactoring);
       kentBeck.books.add(refactoring);
      
       // assertion succeeds
       assertThat(pramodSadalage).usingRecursiveAssertion()
                                 .hasNoNullFields(); 
      Returns:
      this assertions object
      Throws:
      AssertionError - if one or more fields as described above are null.
    • ignoringFields

      public RecursiveAssertionAssert ignoringFields(String... fieldsToIgnore)
      Makes the recursive assertion to ignore the specified fields in the object under test.

      When a field is ignored, all its fields are ignored too.

      Example:

       class Person {
         String name;
         String occupation;
         int age;
         Address address = new Address();
       }
      
       class Address {
         int number;
         String street;
       }
      
       Person sherlock = new Person("Sherlock", "Detective", 60);
       sherlock.address.street = "Baker Street";
       sherlock.address.number = 221;
      
       // assertion succeeds because Person has only String fields except for address and age (address fields are ignored)
       assertThat(sherlock).usingRecursiveAssertion()
                           .ignoringFields("address", "age")
                           .allFieldsSatisfy(field -> field instanceof String);
      
       // assertion fails because of age, address and address.number fields
       assertThat(sherlock).usingRecursiveAssertion()
                           .allFieldsSatisfy(field -> field instanceof String);
      Parameters:
      fieldsToIgnore - the fields to ignore in the object under test.
      Returns:
      this RecursiveAssertionAssert to chain other methods.
    • ignoringFieldsMatchingRegexes

      public RecursiveAssertionAssert ignoringFieldsMatchingRegexes(String... regexes)
      Makes the recursive assertion to ignore the fields matching the specified regexes in the object under test.

      When a field is ignored, all its fields are ignored too.

      Example:

       class Person {
         String name;
         String occupation;
         int age;
         Address address = new Address();
       }
      
       class Address {
         int number;
         String street;
       }
      
       Person sherlock = new Person("Sherlock", "Detective", 60);
       sherlock.address.street = "Baker Street";
       sherlock.address.number = 221;
      
       // assertion succeeds because Person has only String fields except for address and age (address fields are ignored)
       assertThat(sherlock).usingRecursiveAssertion()
                           .ignoringFieldsMatchingRegexes("ad.*", "ag.")
                           .allFieldsSatisfy(field -> field instanceof String);
      
       // assertion fails because of age and address fields (address.number is ignored)
       assertThat(sherlock).usingRecursiveAssertion()
                           .ignoringFieldsMatchingRegexes(".*ber")
                           .allFieldsSatisfy(field -> field instanceof String);
      Parameters:
      regexes - regexes used to ignore fields in the assertion.
      Returns:
      this RecursiveAssertionAssert to chain other methods.
    • ignoringFieldsOfTypes

      public RecursiveAssertionAssert ignoringFieldsOfTypes(Class<?>... typesToIgnore)
      Makes the recursive assertion to ignore the object under test fields of the given types. The fields are ignored if their types exactly match one of the ignored types, for example if a field is a subtype of an ignored type it is not ignored.

      If some object under test fields are null it is not possible to evaluate their types and thus these fields are not ignored.

      When a field is ignored, all its fields are ignored too.

      Example:

       class Person {
         String name;
         String occupation;
         Address address = new Address();
       }
      
       class Address {
         int number;
         String street;
       }
      
       Person sherlock = new Person("Sherlock", "Detective");
       sherlock.address.street = "Baker Street";
       sherlock.address.number = 221;
      
       // assertion succeeds because Person has only String fields except for address  (address fields are ignored)
       assertThat(sherlock).usingRecursiveAssertion()
                           .ignoringFieldsOfTypes(Address.class)
                           .allFieldsSatisfy(field -> field instanceof String);
      
       // assertion fails because of address and address.number fields
       assertThat(sherlock).usingRecursiveAssertion()
                           .allFieldsSatisfy(field -> field instanceof String);
      Parameters:
      typesToIgnore - the types we want to ignore in the object under test fields.
      Returns:
      this RecursiveAssertionAssert to chain other methods.
    • ignoringPrimitiveFields

      public RecursiveAssertionAssert ignoringPrimitiveFields()
      Make the recursive assertion not to run the Predicate over the primitive fields of an object in an object graph, by default asserting over primitives is enabled.

      For example, consider the following class:

       class Example {
          public int primitiveField;
          public String objectField;
        } 

      By default, the assertion being applied recursively will be applied to primitiveField and to objectField. If ignoring primitives it set to true, the assertion will only be applied to objectField.

      If you elect to assert over primitives then it is your own responsibility as a developer to ensure that your Predicate can handle (boxed) primitive arguments.

      Returns:
      this RecursiveAssertionAssert to chain other methods.
    • ignoringAllNullFields

      public RecursiveAssertionAssert ignoringAllNullFields()
      Makes the recursive assertion to ignore all null fields.

       class Person {
         String name;
         String occupation;
         Address address;
       }
      
       class Address {
         int number;
         String street;
       }
      
       Person sherlock = new Person("Sherlock", "Detective");
       sherlock.address = null;
      
       // assertion succeeds as address field is ignored
       assertThat(noName).usingRecursiveAssertion()
                         .ignoringAllNullFields()
                         .allFieldsSatisfy(field -> field instanceof String);
      
       // assertion fails as address, address.number and address.street fields are not evaluated as String, street because it's null.
       assertThat(sherlock).usingRecursiveAssertion()
                           .allFieldsSatisfy(field -> field instanceof String);
      Returns:
      this RecursiveAssertionAssert to chain other methods.
    • withOptionalAssertionPolicy

      public RecursiveAssertionAssert withOptionalAssertionPolicy(org.assertj.core.api.recursive.assertion.RecursiveAssertionConfiguration.OptionalAssertionPolicy optionalAssertionPolicy)
      Makes the recursive assertion to use the specified RecursiveAssertionConfiguration.OptionalAssertionPolicy.

      See RecursiveAssertionConfiguration.OptionalAssertionPolicy for the different possible policies, by default RecursiveAssertionConfiguration.OptionalAssertionPolicy.OPTIONAL_VALUE_ONLY is used.

      Parameters:
      optionalAssertionPolicy - the RecursiveAssertionConfiguration.OptionalAssertionPolicy to use.
      Returns:
      this RecursiveAssertionAssert to chain other methods.
    • withCollectionAssertionPolicy

      public RecursiveAssertionAssert withCollectionAssertionPolicy(org.assertj.core.api.recursive.assertion.RecursiveAssertionConfiguration.CollectionAssertionPolicy collectionAssertionPolicy)
      Makes the recursive assertion to use the specified RecursiveAssertionConfiguration.CollectionAssertionPolicy.

      See RecursiveAssertionConfiguration.CollectionAssertionPolicy for the different possible policies, by default RecursiveAssertionConfiguration.CollectionAssertionPolicy.ELEMENTS_ONLY is used.

      Parameters:
      collectionAssertionPolicy - the RecursiveAssertionConfiguration.CollectionAssertionPolicy to use.
      Returns:
      this RecursiveAssertionAssert to chain other methods.
    • withMapAssertionPolicy

      public RecursiveAssertionAssert withMapAssertionPolicy(org.assertj.core.api.recursive.assertion.RecursiveAssertionConfiguration.MapAssertionPolicy mapAssertionPolicy)
      Makes the recursive assertion to use the specified RecursiveAssertionConfiguration.MapAssertionPolicy.

      See RecursiveAssertionConfiguration.MapAssertionPolicy for the different possible policies, by default RecursiveAssertionConfiguration.MapAssertionPolicy.MAP_VALUES_ONLY is used.

      Parameters:
      mapAssertionPolicy - the RecursiveAssertionConfiguration.MapAssertionPolicy to use.
      Returns:
      this RecursiveAssertionAssert to chain other methods.
    • withIntrospectionStrategy

      public RecursiveAssertionAssert withIntrospectionStrategy(org.assertj.core.api.recursive.assertion.RecursiveAssertionIntrospectionStrategy introspectionStrategy)
      Defines how objects are introspected in the recursive assertion.

      Default to DefaultRecursiveAssertionIntrospectionStrategy that introspects all fields (including inherited ones).

      Parameters:
      introspectionStrategy - the RecursiveAssertionIntrospectionStrategy to use
      Returns:
      this RecursiveAssertionAssert to chain other methods.