Assertj Core Versions Save

AssertJ is a library providing easy to use rich typed assertions

assertj-build-3.25.3

2 months ago

:bug: Bug Fixes

  • Lock maven-clean-plugin version for all modules

Core

  • Fix a performance regression in the recursive comparison related to FieldLocation #3350
  • Don't fail when the recursive comparison checks compared fields in collection elements #3349 (proper fix: #3354)

:hammer: Dependency Upgrades

  • Upgrade to Flatten Maven Plugin 1.6.0 #3335
  • Upgrade to Groovy 4.0.18 #3347
  • Upgrade to Hibernate Core 6.4.2.Final #3338
  • Upgrade to Maven Surefire Report Plugin 3.2.5 #3330
  • Upgrade to PITest Maven 1.15.6 #3348
  • Upgrade to SpotBugs Maven Plugin 4.8.3.0 #3336
  • Upgrade to advanced-security/maven-dependency-submission-action to 4 #3346

:heart: Contributors

Thanks to all the contributors who worked on this release:

@ash211

assertj-build-3.25.2

3 months ago

:bug: Bug Fixes

  • Fix unresolvable Javadoc stylesheet URLs, simplify configuration #3324

Core

  • Fix missing configuration for MatcherAssert soft assertions
  • Make deprecation notice visible in AbstractAssert#asList #3327
  • Recursive comparison uses equals on root object when useOverriddenEquals is enabled #3320
  • satisfiesExactlyInAnyOrder fails if actual overrides equals #3339
  • Avoid calling actual.hashCode() and expected.hashCode() in DualValue #3340
  • Recursive comparison checks for existence of fields in types that parameterize nested unordered iterables #3332

:hammer: Dependency Upgrades

  • Upgrade to EqualsVerifier 3.15.6 #3329
  • Upgrade to Maven Surefire Plugin 3.2.5 #3328
  • Upgrade to Spotless Maven Plugin 2.43.0 #3345

:heart: Contributors

Thanks to all the contributors who worked on this release:

@manusa @davidboden

assertj-build-3.25.1

4 months ago

:jigsaw: Binary Compatibility

The release is:

  • Binary compatible with the previous minor version.
  • Binary incompatible with the previous patch version.

:bug: Bug Fixes

Core

  • Revert "Provide value when assertThatThrownBy/thenThrownBy fail" #3318
  • Revert "fix: containsExactly does not work properly with maps not using equals to compare keys" #3321

assertj-build-3.25.0

4 months ago

:no_entry_sign: Deprecated

Core

  • Deprecate the following date/time related assertions in favor of isCloseTo:
    • isEqualToIgnoringHours
    • isEqualToIgnoringMinutes
    • isEqualToIgnoringSeconds
    • isEqualToIgnoringMillis
    • isEqualToIgnoringNanos
    • isInSameHourAs
    • isInSameMinuteAs
    • isInSameSecondAs
  • Deprecate asList in favor of asInstanceOf #3138

:sparkles: New Features

Core

  • Add Descriptable#describedAs(Supplier<String>)

  • Add isInThePast and isInTheFuture to LocalDate assertions #2933

  • Add isInThePast and isInTheFuture to the missing Java 8 date/time types #2947

  • Add isRecord and isNotRecord to Class assertions #2968

  • Add hasNullValue and doesNotHaveNullValue to AtomicReferenceAssert #2969

  • Add asBoolean|Byte|Short|Int|Long|Float|Double to String assertions #2580

  • Add hasRecordComponents to Class assertions #2995

  • Add getters for field path in ComparisonDifference #3007

  • Allow to compare enum and string fields in the recursive comparison #2616

  • Provide value when assertThatThrownBy / thenThrownBy fail #3043

  • Add isSealed and isNotSealed to Class assertions #3080

  • Add assertThatCharSequence to disambiguate Groovy's GString #3132

  • Change the way the properties are collected using the Class.getMethods() API instead of iterating the class hierarchy using Class.declaredMethods() #3135

  • Add default constructor for RecursiveComparator #3206

  • Add isPrimitive and isNotPrimitive to Class assertions #2722

  • Add anyOf(ThrowingConsumer...) and allOf(ThrowingConsumer...) #3219

    Details

    What was written as:

    assertThat(elements)
      .extracting(Element::getProperty)
      .allSatisfy(p -> assertThat(p).satisfiesAnyOf(
          p1 -> assertThat(p1).isNull(),
          p1 -> assertThat(p1).isNotNull().extracting(Property::getId).isEqualTo(expected)
      ));
    

    can now be shortened to:

    assertThat(elements)
      .extracting(Element::getProperty)
      .allSatisfy(anyOf( // statically imported from Assertions
          p1 -> assertThat(p1).isNull(),
          p1 -> assertThat(p1).isNotNull().extracting(Property::getId).isEqualTo(expected)
      ));
    
  • Show the array/iterable under test in the assertion error message when it is not empty but should have been #3230

:bug: Bug Fixes

Core

  • Compare Java types from javax and com.sun by their equals method in recursive comparison #2928
  • The recursive comparison comparingOnlyFields did not treat array/iterable elements as root objects #2994
  • Fixes a bug when failing assertions on DirectoryStream types #3036
  • Fix handling of null containers in the recursive assertion #3045
  • Handle null values in map entry sets when formatting #3087
  • Fix NPE when expected and actual field values are null #3034
  • Fix NPE on anyMatch when actual contains null and Objects::isNull is used as predicate #3151
  • Fix misleading subsequence failure messages in string assertions #3166
  • Do not ignore nested fields of types specified in comparingOnlyFieldsOfTypes #3207
  • containsExactly does not work properly with maps not using equals to compare keys #2165
  • Escape percentage in shouldContainExactly error message #3288
  • Fix recursive comparison of ignored types in unordered collection #3287

:zap: Improvements

  • Add Spotless #3115

Core

  • Use Bnd feature to write resolved bndrun files to output folder #2902

  • Add Throwable stack trace to ShouldHaveClause #2872

  • Avoid copy of any Collection instance in Iterables::assertContains

  • Add Throwable stack trace to ShouldHaveRootCauseInstance and ShouldHaveRootCauseExactlyInstance #2910

  • Add missing description to nested condition #2755

  • Make nestable condition factory accept conditions on super types #2905

  • Add varargs overload to Assert::hasString and Assert::doesNotHaveString #2945

  • Improve recursive comparison performance by caching field and field names result #2979

  • Document performance cost of ignoring collection order

  • Track visited values and their comparison differences so that they can be reused #2954

  • Use hash code for compareUnorderedIterables to improve performance in some common cases #3020

  • Improve recursive comparison error message regarding equals methods used for JDK types #2678

  • Format large arrays as strings #3065

  • Remove null check as isArray already performs it

  • Fix PrimitiveArralList/TransformlingList test file names #3124

  • Add exception for usages of isEqualTo and isNotEqualTo on assertions #2921

    Details

    Before this change, the following code:

    AbstractAssert<?, ?> assertion = assertThat(something);
    assertThat(assertion).isEqualTo(assertion);
    

    would throw an exception with a message about equals being unsupported, suggesting to use isEqualTo instead. The message is somewhat confusing to the reader, since isEqualTo is indeed used, and is because isEqualTo internally relies on the equals of actual, which is an AbstractAssert instance and throws the exception above.

    isEqualTo and isNotEqualTo now check if actual is an assertion instance and raise an UnsupportedOperationException if so, with a message suggesting to use isSameAs and isNotSameAs instead.

    This is, for example, useful for testing custom assertion types for extension libraries, where the use of satisfies instead of isEqualTo may be desirable.

  • Add check for missing fields in recursive comparison where specific fields are requested for comparison

  • Improve efficiency of iterable string conversion #3123

  • Add more tests for usingRecursiveComparison #2790

  • Checks that compared fields exist before running the recursive comparison #3129

  • Remove maven-surefire-plugin duplicate version #3180

  • Remove Maven default goal #3182

  • Add dependency graph workflow

  • Normalize non-breaking spaces like regular white spaces #3120

  • AbstractOffsetDateTimeAssert::isBetween parameter names should use inclusive, not exclusive #3217

  • Invoke isNotNull in returns and doesNotReturn #3224

  • Cache node names in ComparingFields, ComparingProperties #3242

  • Cache node names in ComparingNormalizedFields

  • Use simpler syntax in DefaultRecursiveComparisonIntrospectionStrategy.getChildrenNodeNamesOf

  • Update to Contributor Covenant Code of Conduct v2.1

  • Correct contains assertion Javadoc to reflect method behavior in case actual is not empty and the group of values to look for is #3256

  • Fix Javadoc typos #3265

  • Improving null-safety of isEqualToNormalizingNewlines #2776

  • Speed up for BinaryDiff performance #3193

  • Upgrade workflows to Java 21 #3191

  • Apply flatten-maven-plugin to assertj-core and assertj-guava #3311

:hammer: Dependency Upgrades

  • Upgrade to Bnd 7.0.0 #3211
  • Upgrade to Byte Buddy 1.14.11 #3304
  • Upgrade to Commons IO 2.14.0 #3200
  • Upgrade to Commons Lang 3.14.0 #3269
  • Upgrade to EqualsVerifier 3.15.5 #3305
  • Upgrade to Flatten Maven Plugin 1.5.0 #3041
  • Upgrade to GMavenPlus Plugin 3.0.2 #3199
  • Upgrade to Groovy 4.0.17 #3306
  • Upgrade to Guava 32.1.3-jre #3218
  • Upgrade to Hibernate Core 6.4.1.Final #3299
  • Upgrade to Jackson Databind 2.16.0 #3258
  • Upgrade to JaCoCo Maven Plugin 0.8.11
  • Upgrade to Japicmp Maven Plugin 0.18.2 #3228
  • Upgrade to Java Servlet API 4.0.1 #2934
  • Upgrade to JBoss Logging 3.5.3.Final #3101
  • Upgrade to JUnit BOM 5.10.1 #3254
  • Upgrade to Kotlin 1.9.22 #3303
  • Upgrade to License Maven Plugin 4.3 #3198
  • Upgrade to Maven 3.9.6
  • Upgrade to Maven Clean Plugin 3.3.2 #3240
  • Upgrade to Maven Compiler Plugin 3.12.1 #3310
  • Upgrade to Maven Deploy Plugin 3.1.1 #3001
  • Upgrade to Maven Enforcer Plugin 3.4.1 #3172
  • Upgrade to Maven GPG Plugin 3.1.0 #3040
  • Upgrade to Maven Install Plugin 3.1.1 #2999
  • Upgrade to Maven Javadoc Plugin 3.6.2 #3253
  • Upgrade to Maven Project Info Reports Plugin 3.5.0 #3267
  • Upgrade to Maven Release Plugin 3.0.1 #3068
  • Upgrade to Maven Resources Plugin 3.3.1 #3000
  • Upgrade to Maven Source Plugin 3.3.0 #3057
  • Upgrade to Maven Surefire Plugin 3.2.2 #3252
  • Upgrade to Maven Surefire Report Plugin 3.2.2 #3255
  • Upgrade to OpenTest4J 1.3.0 #3122
  • Upgrade to OSGi System Bundle 3.18.600 #3286
  • Upgrade to PITest 1.1.2 #3163
  • Upgrade to PITest JUnit 5 Plugin 1.2.1 #3236
  • Upgrade to PITest Maven 1.15.2 #3237
  • Upgrade to Sonar Maven Plugin 3.10.0.2594 #3178
  • Upgrade to SpotBugs Maven Plugin 4.8.1.0 #3257
  • Upgrade to Spotless Maven Plugin 2.41.1 #3285
  • Upgrade to Spring Core 5.3.31 #3259
  • Upgrade to TestNG 7.9.0 #3312
  • Upgrade to Versions Maven Plugin 2.16.2 #3260
  • Upgrade to actions/checkout 4 #3169
  • Upgrade to actions/setup-java 4 #3279
  • Upgrade to actions/upload-artifact 4 #3298
  • Upgrade to dawidd6/action-download-artifact 3 #3296

:heart: Contributors

Thanks to all the contributors who worked on this release:

@bjhargrave @vlsi @Ds2994 @StefanBratanov @alex859 @ascopes @ljrmorgan @ghkim3221 @hezean @matthew-leng @etellman @hjir @amodolo @armandino @aindriu-aiven @Bananeweizen @JohnBryte @ManuelG28 @maximedezette @radistao @ykardziyaka @wouterpolet @sarajuhosova @pbacz @Gabriel-Darbord @Nacho321 @marcela-cardona-s @matthiaskraaz @quaff @grigala @martinfrancois @georgebax

assertj-build-3.24.0

7 months ago

:no_entry_sign: Deprecated

Core

  • Deprecate ObjectAssert(AtomicReference) #2795

:sparkles: New Features

  • Add Bill of Materials for AssertJ #2748

Core

  • Introduce IntrospectionStrategy for recursive comparison and assertion to allow configuring how objects are introspected (thanks @mikybars for the contribution).

  • Add allFieldsSatisfy and hasNoNullFields recursive assertions #2211

    Details

    allFieldsSatisfy verifies that a given Predicate is met for all the fields in the field graph of the object under test (i.e., each field is evaluated recursively), but not for the object under test itself.

    For example, if actual is an instance of class A, A has a B field, and B has a C field, then allFieldsSatisfy checks A’s B field and B’s C field, and all C’s fields.

    hasNoNullFields verifies that none of the fields are null in the field graph of the object under test (i.e., each field is evaluated recursively), but not the object under test itself.

    It is possible to exclude some fields with any of these methods:

    • ignoringFields(String... fieldsToIgnore) - the assertion ignores the specified fields in the object under test
    • ignoringFieldsMatchingRegexes(String... regexes) - the assertion ignores the fields matching the specified regexes in the object under test
    • ignoringFieldsOfTypes(Class<?>... typesToIgnore) - the assertion ignores the object under test fields of the given types
    • ignoringPrimitiveFields() - avoid running the assertion on primitive fields

    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);
    
    // best rewritten with `hasNoNullFields()`
    assertThat(pramodSadalage).usingRecursiveAssertion()
                              .hasNoNullFields();
    
  • Add withEqualsForFieldsMatchingRegexes to the recursive comparison #2711

    Details

    Allows registering a BiPredicate to compare fields whose location matches the given regexes.

    A typical usage consists of comparing double/float fields with a given precision.

    The fields are evaluated from the root object. For example, if Foo has a Bar field and both have an id field, one can register a BiPredicate for Foo and Bar id by calling:

    withEqualsForFieldsMatchingRegexes(idBiPredicate, ".*id")
    

    or:

    withEqualsForFieldsMatchingRegexes(idBiPredicate, "foo.*id")
    

    Example:

    class TolkienCharacter {
      String name;
      double height;
      double weight;
    }
    
    TolkienCharacter frodo = new TolkienCharacter("Frodo", 1.2, 40);
    TolkienCharacter tallerFrodo = new TolkienCharacter("Frodo", 1.3, 40.5);
    
    BiPredicate<Double, Double> closeEnough = (d1, d2) -> Math.abs(d1 - d2) <= 0.5;
    
    // assertion succeeds as both weight and height diff is less than 0.5
    assertThat(frodo).usingRecursiveComparison()
                     .withEqualsForFieldsMatchingRegexes(closeEnough, ".eight")
                     .isEqualTo(tallerFrodo);
    
  • Add comparingOnlyFieldsOfTypes to the recursive comparison #2794

    Details

    Makes the recursive comparison to only compare given actual fields of the specified types and their subfields (no other fields will be compared).

    Specifying a field of type will make all its subfields to be compared. For example, specifying the Person type will lead to comparing Person.name, Person.address and all other Person fields. In case actual's field is null, expected's field type will be checked to match one of the given types (we assume actual and expected fields have the same type).

    comparingOnlyFieldsOfTypes can be combined with comparingOnlyFields(String...) to compare fields of the given types or names (union of both sets of fields).

    comparingOnlyFieldsOfTypes can be also combined with ignoring fields or compare only fields by name methods to restrict further the fields actually compared, the resulting compared fields = {specified compared fields of types} - {specified ignored fields}.

    For example, if the specified compared fields of types are {String.class, Integer.class, Double.class}, when there are fields String foo, Integer baz and Double bar and the ignored fields = {"bar"} set with ignoringFields(String...) that will remove bar field from comparison, then only {foo, baz} fields will be compared.

    Example:

    class Person {
      String name;
      double height;
      Home home = new Home();
    }
    
    class Home {
      Address address = new Address();
    }
    
    class Address {
      int number;
      String street;
    }
    
    Person sherlock = new Person("Sherlock", 1.80);
    sherlock.home.address.street = "Baker Street";
    sherlock.home.address.number = 221;
    
    Person moriarty = new Person("Moriarty", 1.80);
    moriarty.home.address.street = "Butcher Street";
    moriarty.home.address.number = 221;
    
    
    // assertion succeeds as it only compared fields height and home.address.number since their types match compared types
    assertThat(sherlock).usingRecursiveComparison()
                        .comparingOnlyFieldsOfTypes(Integer.class, Double.class)
                        .isEqualTo(Moriarty);
    
    // assertion fails as home.address.street fields differ (Home fields and its subfields were compared)
    assertThat(sherlock).usingRecursiveComparison()
                        .comparingOnlyFieldsOfTypes(Home.class)
                        .isEqualTo(moriarty);
    
  • Add isIn / isNotIn assertions to the recursive comparison #2794

    Details

    isIn verifies that actual is present in the given iterable/array, while isNotIn verifies that actual is not present in the given iterable/array. Both compare values with the recursive comparison.

    class Person {
      String name;
      double height;
      Home home = new Home();
    }
    
    class Home {
      Address address = new Address();
    }
    
    class Address {
      int number;
      String street;
    }
    
    Person sherlock = new Person("Sherlock", 1.80);
    sherlock.home.ownedSince = new Date(123);
    sherlock.home.address.street = "Baker Street";
    sherlock.home.address.number = 221;
    
    Person sherlock2 = new Person("Sherlock", 1.80);
    sherlock2.home.ownedSince = new Date(123);
    sherlock2.home.address.street = "Baker Street";
    sherlock2.home.address.number = 221;
    
    Person watson = new Person("Watson", 1.70);
    watson.home.ownedSince = new Date(123);
    watson.home.address.street = "Baker Street";
    watson.home.address.number = 221;
    
    Person moriarty = new Person("Moriarty", 1.80);
    moriarty.home.ownedSince = new Date(123);
    moriarty.home.address.street = "Butcher Street";
    moriarty.home.address.number = 221;
    
    // assertion succeeds as sherlock and sherlock2 data are the same but not for watson and moriarty
    assertThat(sherlock).usingRecursiveComparison()
                        .isIn(sherlock2, Moriarty)
                        .isNotIn(watson, moriarty);
    
  • Add RecursiveComparator that uses the recursive comparison for any assertions

  • Add satisfiesOnlyOnce to iterable, array, and atomic array assertions #2691

    Details

    Verifies that there is exactly one element in the iterable/array under test that satisfies the given Consumer.

    Example:

    List<String> starWarsCharacterNames = List.of("Luke", "Leia", "Yoda");
    
    // these assertions succeed:
    assertThat(starWarsCharacterNames).satisfiesOnlyOnce(name -> assertThat(name).contains("Y")) // matches only "Yoda"
                                      .satisfiesOnlyOnce(name -> assertThat(name).contains("Lu")) // matches only "Luke"
                                      .satisfiesOnlyOnce(name -> assertThat(name).contains("Le")); // matches only "Leia"
    
    // this assertion fails because the requirements are satisfied two times
    assertThat(starWarsCharacterNames).satisfiesOnlyOnce(name -> assertThat(name).contains("a")); // matches "Leia" and "Yoda"
    
    // this assertion fails because no element contains "Han"
    assertThat(starWarsCharacterNames).satisfiesOnlyOnce(name -> assertThat(name).contains("Han"));
    
  • Add isAssignableTo to Class assertions #2611

    Details

    Verifies that the Class under test is assignable to the given one.

    Example:

    class Jedi {}
    class HumanJedi extends Jedi {}
    
    // this assertion succeeds
    assertThat(HumanJedi.class).isAssignableTo(Jedi.class);
    
    // this assertion fails
    assertThat(Jedi.class).isAssignableTo(HumanJedi.class);
    
  • Add withThrowableThat to ease Future / CompletableFuture throwable assertions #2704

    Details

    Returns a ThrowableAssertAlternative to chain assertions on the underlying throwable for Future / CompletableFuture assertions.

    Example:

    CompletableFuture<Void> completableFuture = new CompletableFuture<>();
    completableFuture.completeExceptionally(new RuntimeException("boom!"));
    
    then(completableFuture).failsWithin(Duration.ofMillis(1))
                           .withThrowableThat()
                           .isInstanceOf(ExecutionException.class)
                           .withMessageContaining("boom!");
    
  • Add matchesSatisfying for checking pattern followed by assertion on matcher groups #2723

    Details

    Verifies that the actual CharSequence matches the given regular expression pattern, then accepts the given Consumer<Matcher> to do further verification on the matcher.

    Example:

    assertThat("Frodo").matchesSatisfying("..(o.o)", matcher -> assertThat(matcher.group(1)).isEqualTo("odo"));
    
    // same assertion but with a Pattern
    Pattern pattern = Pattern.compile("..(o.o)");
    assertThat("Frodo").matchesSatisfying(pattern, matcher -> assertThat(matcher.group(1)).isEqualTo("odo"));
    
  • Add NestableCondition #2726

    Details

    NestableCondition::nestable is a building block defining a more precise condition on complex objects. It allows the creation of readable assertions and produces nicer assertion error messages.

    Example:

    import static org.assertj.core.condition.NestableCondition.nestable;
    import static org.assertj.core.condition.VerboseCondition.verboseCondition;
    
    class Customer {
      final String name;
      final Address address;
    
      Customer(String name, Address address) {
        this.name = name;
        this.address = address;
      }
    }
    
    class Address {
      final String firstLine;
      final String postcode;
    
      Address(String firstLine, String postcode) {
        this.firstLine = firstLine;
        this.postcode = postcode;
      }
    }
    
    static Condition<Customer> name(String expected) {
      return new Condition<>(
        it -> expected.equals(it.name),
        "name: " + expected
      );
    }
    
    static Condition<Customer> customer(Condition<Customer>... conditions) {
      return nestable("person", conditions);
    }
    
    static Condition<Address> firstLine(String expected) {
      return new Condition<>(
        it -> expected.equals(it.firstLine),
        "first line: " + expected
      );
    }
    
    static Condition<Address> postcode(String expected) {
      return new Condition<>(
        it -> expected.equals(it.postcode),
        "postcode: " + expected
      );
    }
    
    static Condition<Customer> address(Condition<Address>... conditions) {
      return nestable(
        "address",
        customer -> customer.address,
        conditions
      );
    }
    

    An assertion written like:

    assertThat(customer).is(
      customer(
        name("John"),
        address(
          firstLine("3"),
          postcode("KM3 8SP")
        )
      )
    );
    

    will produce an easy-to-read assertion error:

    Expecting actual:
      org.assertj.core.condition.Customer@27ff5d15
    to be:
      [✗] person:[
          [✓] name: John,
          [✗] address:[
            [✗] first line: 3,
            [✓] postcode: KM3 8SP
          ]
      ]
    

    For an even better assertion error, see VerboseCondition.

  • Add isAlphabetic to CharSequence assertions #2731

    Details

    Verifies that the actual CharSequence is alphabetic by checking it against the \p{Alpha}+ regex pattern POSIX character classes (US-ASCII only).

    Example:

    // assertions will pass
    assertThat("lego").isAlphabetic();
    assertThat("a").isAlphabetic();
    assertThat("Lego").isAlphabetic();
    
    // assertions will fail
    assertThat("1").isAlphabetic();
    assertThat(" ").isAlphabetic();
    assertThat("").isAlphabetic();
    assertThat("L3go").isAlphabetic();
    
  • Add isAlphanumeric to CharSequence assertions #2731

    Details

    Verifies that the actual CharSequence is alphanumeric by checking it against the \p{Alnum}+ regex pattern POSIX character classes (US-ASCII only).

    Example:

    // assertions will pass
    assertThat("lego").isAlphanumeric();
    assertThat("a1").isAlphanumeric();
    assertThat("L3go").isAlphanumeric();
    
    // assertions will fail
    assertThat("!").isAlphanumeric();
    assertThat("").isAlphanumeric();
    assertThat(" ").isAlphanumeric();
    assertThat("L3go!").isAlphanumeric();
    
  • Add isASCII to CharSequence assertions #2731

    Details

    Verifies that the actual CharSequence is ASCII by checking it against the \p{ASCII}+ regex pattern POSIX character classes (US-ASCII only).

    Example:

    // assertions will pass
    assertThat("lego").isASCII();
    assertThat("a1").isASCII();
    assertThat("L3go").isASCII();
    
    // assertions will fail
    assertThat("").isASCII();
    assertThat("♪").isASCII();
    assertThat("⌃").isASCII();
    assertThat("L3go123⌃00abc").isASCII();
    
  • Add isHexadecimal to CharSequence assertions #2731

    Details

    Verifies that the actual CharSequence is hexadecimal by checking it against the \p{XDigit}+ regex pattern POSIX character classes (US-ASCII only).

    Example:

    // assertions will pass
    assertThat("A").isHexadecimal();
    assertThat("2").isHexadecimal();
    
    // assertions will fail
    assertThat("!").isHexadecimal();
    assertThat("").isHexadecimal();
    assertThat(" ").isHexadecimal();
    assertThat("Z").isHexadecimal();
    assertThat("L3go!").isHexadecimal();
    
  • Add isPrintable to CharSequence assertions #2731

    Details

    Verifies that the actual CharSequence is printable by checking it against the \p{Print}+ regex pattern POSIX character classes (US-ASCII only).

    Example:

    // assertions will pass
    assertThat("2").isPrintable();
    assertThat("a").isPrintable();
    assertThat("~").isPrintable();
    assertThat("").isPrintable();
    
    // assertions will fail
    assertThat("\t").isPrintable();
    assertThat("§").isPrintable();
    assertThat("©").isPrintable();
    assertThat("\n").isPrintable();
    
  • Add isVisible to CharSequence assertions #2731

    Details

    Verifies that the actual CharSequence is visible by checking it against the \p{Graph}+ regex pattern POSIX character classes (US-ASCII only).

    Example:

    // assertions will pass
    assertThat("2").isVisible();
    assertThat("a").isVisible();
    assertThat(".").isVisible();
    
    // assertions will fail
    assertThat("\t").isVisible();
    assertThat("\n").isVisible();
    assertThat("").isVisible();
    assertThat(" ").isVisible();
    
  • Add isUnmodifiable to Map assertions #2458

    Details

    Verifies that the map under test is unmodifiable, i.e. throws an UnsupportedOperationException with any attempt to modify the map.

    Example:

    // assertions succeeds
    assertThat(Collections.unmodifiableMap(new HashMap<>())).isUnmodifiable();
    
    // assertions fails
    assertThat(new HashMap<>()).isUnmodifiable();
    
  • Add isExecutable to File assertions #2829

    Details

    Verifies that the file under test is executable.

    Example:

    File tmpFile = java.nio.file.Files.createTempFile("executable_file", ".sh").toFile();
    
    tmpFile.setExecutable(true);
    // assertions succeeds
    assertThat(tmpFile).isExecutable();
    
    tmpFile.setExecutable(false);
    // assertions fails
    assertThat(tmpFile).isExecutable();
    
  • Add hasMessageMatching(Pattern) to Throwable assertions #2853

    Details

    Verifies that the message of the Throwable under test matches the given Pattern regular expression.

    Example:

    Throwable throwable = new IllegalArgumentException("wrong amount 123");
    
    // assertion succeeds
    assertThat(throwable).hasMessageMatching(Pattern.compile("wrong amount [0-9]*"));
    
    // assertion fails
    assertThat(throwable).hasMessageMatching(Pattern.compile("wrong amount [0-9]* euros"));
    

Guava

  • AssertJ Guava is now part of the AssertJ multimodule and follows the same versioning

:bug: Bug Fixes

Core

  • Avoid reflection in recursive comparison for types in sun.* packages #2891
  • Honor custom type comparators with returns and doesNotReturn #2725
  • Fix ignoringOverriddenEqualsForFieldsMatchingRegexes that was checking field class instead of the field path
  • Add support for soft assertions when calling isThrownBy #2699
  • Fix isCloseTo Javadoc example for Date assertions #2890

:zap: Improvements

Core

  • Generalize custom format creation to support any CharSequence #2735
  • Improve containsExactly error message by printing the indices where a mismatch occurred #2638
  • Throw org.opentest4j.AssertionFailedError for containsExactly to get the actual vs. expected diff in the IDE #2697
  • Fix some typos and grammar in project documentation #2656
  • Fix typo in docs for assertIsEqualToNormalizingNewlines #2677
  • Fix javadoc for within(long, TemporalUnit) #2801
  • Let CaseInsensitiveStringComparator delegate to compareToIgnoreCase #2663
  • Use actual Map type when invoking copying constructor #2710
  • Improve isBetween assertion performance by only building the error message when needed #2884
  • Avoid a copy in assertContains when actual is already a Collection #2220
  • Repair code style issues in org.assertj.core.internal.Dates #2763
  • Reduce RealNumbers constructors' visibility to protected #2772
  • Use getParameterCount rather than getParameterTypes().length #2813
  • Return cache in setup-java action #2802
  • Fix test results summary #2803
  • Remove public modifier to fix some sonar violations
  • Clean up unused imports
  • Migrate MatcherShouldMatch_create_Test and StandardRepresentation_toStringOf_AtomicReferences_Test to JUnit Jupiter
  • Require Java 17 in Gitpod configuration
  • Swap out deprecated-for-removal methods in BDDAssertions_then_Test.java #2644
  • Fix 95 warnings produced on JDK-17 with -Xlint:all #2648
  • Fix spurious Future tests failure on Windows runners #2649
  • Fix CI allowing add-label to fail in binary-compatibility.yml #2667
  • Improve CI output #2669
  • Reset global state more aggressively in tests #2670
  • Fix incomplete test for given(Duration) in BDDAssumptionsTest #2686
  • Fix some test flakiness #2657
  • Fix some additional compilation warnings and deprecated JDK API usages
  • Remove CodeQL workflow
  • Reuse spies in Path tests #2826
  • Reuse mocks and spies in File tests #2827
  • Remove unnecessary test for MapEntry::hashCode
  • Improve JaCoCo configuration
  • Use oracle-actions/setup-java for cross-version workflow #2658
  • Some more Turkish locale cleanup
  • Use specific labels for Dependabot
  • Switch license URL to HTTPS
  • Move assumptions related integration tests into separate modules #2737
  • Move OSGi related integration tests into separate modules #2742
  • Move performance tests into separate modules #2743
  • Add integration test infrastructure for Groovy #2762
  • Add integration test infrastructure for Kotlin #2788
  • Add editorconfig for Kotlin files
  • Fix locale handling for ignoring case assertions #2690
  • Enforce test only dependencies in test modules
  • Move japicmp common configuration to the parent POM #2875
  • Allow Java 20 with Groovy tests #2816
  • Add Java 21, skip JaCoCo on cross-version workflow #2876

:hammer: Dependency Upgrades

  • Upgrade to Bnd 6.4.0 #2860
  • Upgrade to Byte Buddy 1.12.20 #2880
  • Upgrade to EqualsVerifier 3.12.3 #2877
  • Upgrade to GMavenPlus Plugin 2.1.0 #2818
  • Upgrade to Groovy 4.0.7 #2889
  • Upgrade to Hibernate Core 6.1.6.Final #2869
  • Upgrade to Jackson Databind 2.14.1 #2854
  • Upgrade to Japicmp Maven Plugin 0.17.1 #2847
  • Upgrade to JUnit BOM 5.9.1 #2785
  • Upgrade to JUnit Pioneer 1.9.1 #2698
  • Upgrade to Maven 3.8.7
  • Upgrade to Maven Install Plugin 3.1.0 #2851
  • Upgrade to Maven JAR Plugin 3.3.0 #2782
  • Upgrade to Maven Javadoc Plugin 3.4.1 #2738
  • Upgrade to Maven Project Info Reports Plugin #2741
  • Upgrade to Maven Site Plugin #2730
  • Upgrade to Mockito BOM #2893
  • Upgrade to Kotlin 1.8.0 #2892
  • Upgrade to OSGi System Bundle #2868
  • Upgrade to PITest 1.0.3 #2866
  • Upgrade to PITest Maven 1.10.4 #2898
  • Upgrade to SpotBugs Maven Plugin 4.7.3.0 #2834
  • Upgrade to Spring Core 5.3.24
  • Upgrade to TestNG 7.7.1 #2873
  • Upgrade to Versions Maven Plugin 2.14.2 #2888

:heart: Contributors

Thanks to all the contributors who worked on this release:

@ascopes @nstdio @Bananeweizen @mbaechler @StefanBratanov @stevenschlansker @jessicant @MartinWitt @nith2001 @WojciechZankowski @drakulavich @ChrisZoet @DirkToewe @3flex @opwvhk @alex859 @Giovds @NeshkaD @snuyanzin @rostIvan @remika @micd

Special thanks to those who contributed many internal improvements to our test suite, much appreciated!

assertj-core-3.23.1

7 months ago

:bug: Bug Fixes

Core

  • Downgrade JUnit Jupiter from 5.9.0-M1 to 5.8.2 #2637

assertj-build-3.24.2

7 months ago

:bug: Bug Fixes

Core

  • Remove unintentional @Deprecated from containsOnlyDigits of CharSequence assertions #2909
  • Fix a regression that caused NPE on contains of Iterable assertions when the iterable under test is an anonymous subclass of Collection #2906

assertj-build-3.24.1

7 months ago

:bug: Bug Fixes

Core

  • Fix a regression that caused NPE on returns / doesNotReturn when the expected value is null #2901