Repository: assertj/assertj
Pull request #3706 (2024-12-18 21:59:30)

chore(deps-dev): bump org.hibernate.orm:hibernate-core from 6.6.3.Final to 6.6.4.Final
Bumps [org.hibernate.orm:hibernate-core](https://github.com/hibernate/hibernate-orm) from 6.6.3.Final to 6.6.4.Final.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/hibernate/hibernate-orm/releases">org.hibernate.orm:hibernate-core's releases</a>.</em></p>
<blockquote>
<h1>Hibernate ORM 6.6.4.Final released</h1>
<p>Today, we published a new release of Hibernate ORM 6.6: 6.6.4.Final.</p>
<p>You can find the full list of 6.6.4.Final changes <a href="https://hibernate.atlassian.net/issues/?jql=project%20%3D%20HHH%20AND%20fixVersion%20%3D%206.6.4">here</a>.</p>
<h2>What's new</h2>
<p>This release introduces a few minor improvements as well as bug fixes.</p>
<h2>Conclusion</h2>
<p>For additional details, see:</p>
<ul>
<li>the <a href="https://hibernate.org/orm/releases/6.6/">release page</a></li>
<li>the <a href="https://docs.jboss.org/hibernate/orm/6.6/migration-guide/migration-guide.html">Migration Guide</a></li>
<li>the <a href="https://docs.jboss.org/hibernate/orm/6.6/introduction/html_single/Hibernate_Introduction.html">Introduction Guide</a></li>
<li>the <a href="https://docs.jboss.org/hibernate/orm/6.6/userguide/html_single/Hibernate_User_Guide.html">User Guide</a></li>
</ul>
<p>See also the following resources related to supported APIs:</p>
<ul>
<li>the <a href="https://hibernate.org/community/compatibility-policy/">compatibility policy</a></li>
<li>the <a href="https://docs.jboss.org/hibernate/orm/6.6/incubating/incubating.txt">incubating API report</a> (<code>@Incubating</code>)</li>
<li>the <a href="https://docs.jboss.org/hibernate/orm/6.6/deprecated/deprecated.txt">deprecated API report</a> (<code>@Deprecated</code> + <code>@Remove</code>)</li>
<li>the <a href="https://docs.jboss.org/hibernate/orm/6.6/internals/internal.txt">internal API report</a> (internal packages, <code>@Internal</code>)</li>
</ul>
<p>Visit the <a href="https://hibernate.org/community/">website</a> for details on getting in touch with us.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/hibernate/hibernate-orm/blob/6.6.4/changelog.txt">org.hibernate.orm:hibernate-core's changelog</a>.</em></p>
<blockquote>
<h2>Changes in 6.6.4.Final (December 18, 2024)</h2>
<p><a href="https://hibernate.atlassian.net/projects/HHH/versions/32370">https://hibernate.atlassian.net/projects/HHH/versions/32370</a></p>
<p>** Bug
* [HHH-18949] - Hibernate Processor should not insert underscores within uppercase names
* [HHH-18932] - Wrongly using FK column instead of PK when using joined alias
* [HHH-18912] - ORM release process
* [HHH-18904] - Bytecode Enhancement fails with UnsupportedEnhancementStrategy.FAIL for pre-persist method
* [HHH-18903] - Bytecode enhancement fails for entities that contain a method named get
* [HHH-18872] - ConcreteProxy type not restored from 2LC when loading a ManyToOne
* [HHH-18868] - Wrong behaviour of getAttribute method in impl. of ManagedType when scattered id attributes are used in MappedSuperclass
* [HHH-18863] - jpamodelgen 6.6 performance issue in Eclipse IDE
* [HHH-18850] - createCountQuery with Hibernate 6.6.2
* [HHH-18709] - CriteriaUpdate involving JSON field containing Map<!-- raw HTML omitted --> results in SemanticException
* [HHH-18689] - 'FULL' query cache sometimes incomplete
* [HHH-18629] - Inconsistent column alias generated while result class is used for placeholder
* [HHH-18583] - Joined + discriminator inheritance treat in where clause not restricting to subtype
* [HHH-18384] - <a href="https://github.com/JoinColumnsOrFormulas"><code>@​JoinColumnsOrFormulas</code></a> broken
* [HHH-18274] - Problems with generics in queries; proposed partial solution
* [HHH-17838] - <a href="https://github.com/OneToOne"><code>@​OneToOne</code></a> relationship + <a href="https://github.com/Embeddable"><code>@​Embeddable</code></a> keys + FetchType.LAZY fail in most recent version
* [HHH-17612] - DefaultRevisionEntity: Illegal argument on static metamodel field injection
* [HHH-14725] - Using a InputStream with BlobProxy and Envers results in  java.sql.SQLException: could not reset reader
* [HHH-13815] - TransientObjectException after merging a bidirectional one-to-many with orphan deletion
* [HHH-13790] - Temporary session not being closed
* [HHH-13377] - Lazy loaded properties of bytecode enhanced entity are left stale after refresh of entity</p>
<p>** Sub-task
* [HHH-18369] - Support Informix matches() function
* [HHH-18367] - Informix sum on case expression error
* [HHH-18365] - Informix function bit_length() error
* [HHH-18364] - Informix function locate() error
* [HHH-18363] - Informix component nullness check error
* [HHH-18362] - Informix function substring() error
* [HHH-18361] - Informix current_time error
* [HHH-18360] - Informix function str() error</p>
<p>** Task
* [HHH-18917] - Follow all of the JavaBeans rules in enhance/internal/bytebuddy/EnhancerImpl when checking if a class can be enhanced
* [HHH-18906] - Allow specifying UnsupportedEnhancementStrategy for Hibernate testing</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/hibernate/hibernate-orm/commit/c22c25b7d7743ae89ae1f82a6ae1e2ff7802ed17"><code>c22c25b</code></a> Pre-steps for release : <code>6.6.4.Final</code></li>
<li><a href="https://github.com/hibernate/hibernate-orm/commit/0afa7458cafd5d0dd5d240ac62ac69534fe17a5b"><code>0afa745</code></a> HHH-18912 - ORM release process</li>
<li><a href="https://github.com/hibernate/hibernate-orm/commit/8956c0a585e8e9edc205a490a1a9a372dcf1bb8f"><code>8956c0a</code></a> HHH-18912 - ORM release process</li>
<li><a href="https://github.com/hibernate/hibernate-orm/commit/376dbb17345410fd4620afd580608822d1b8e9ed"><code>376dbb1</code></a> Try fixing publishing</li>
<li><a href="https://github.com/hibernate/hibernate-orm/commit/9c4d33b00d512eb558aa39da914df57ca3d3b71d"><code>9c4d33b</code></a> Various release script fixes</li>
<li><a href="https://github.com/hibernate/hibernate-orm/commit/e685425fdbc8e3c2ed8214544d2162b697e24aca"><code>e685425</code></a> don't generate &quot;auxiliary&quot; members for Jakarta Data static metamodel</li>
<li><a href="https://github.com/hibernate/hibernate-orm/commit/103b2f80615d93d7774ac1be856fadea5d0a4b7f"><code>103b2f8</code></a> HHH-14725 Fixed test</li>
<li><a href="https://github.com/hibernate/hibernate-orm/commit/0b61cc3d3a1fa3e2eb153ec4fe6c66dd8aedd75c"><code>0b61cc3</code></a> HHH-14725 Fix reset handling on BlobProxy</li>
<li><a href="https://github.com/hibernate/hibernate-orm/commit/0b28e2c45de895e7fe0d896a649d405740cb555e"><code>0b28e2c</code></a> HHH-14725 Fixed test</li>
<li><a href="https://github.com/hibernate/hibernate-orm/commit/6300c34a2c28efae1f120216b18088f3350883ac"><code>6300c34</code></a> HHH-14725 Adjust test to use byte array, update Javadoc</li>
<li>Additional commits viewable in <a href="https://github.com/hibernate/hibernate-orm/compare/6.6.3...6.6.4">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.hibernate.orm:hibernate-core&package-manager=maven&previous-version=6.6.3.Final&new-version=6.6.4.Final)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/assertj-core/pom.xml b/assertj-core/pom.xml
index 33bef49dd..cef592c93 100644
--- a/assertj-core/pom.xml
+++ b/assertj-core/pom.xml
@@ -154,7 +154,7 @@
     <dependency>
       <groupId>org.hibernate.orm</groupId>
       <artifactId>hibernate-core</artifactId>
-      <version>6.6.3.Final</version>
+      <version>6.6.4.Final</version>
       <scope>test</scope>
       <exclusions>
         <exclusion>
diff --git a/assertj-core/src/main/java/org/assertj/core/api/AbstractAssert.java b/assertj-core/src/main/java/org/assertj/core/api/AbstractAssert.java
index 103528e63..16e442c74 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/AbstractAssert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/AbstractAssert.java
@@ -31,6 +31,7 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.function.BiPredicate;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
@@ -717,6 +718,20 @@ public abstract class AbstractAssert<SELF extends AbstractAssert<SELF, ACTUAL>,
     return myself;
   }
 
+  /** {@inheritDoc} */
+  @Override
+  @CheckReturnValue
+  public SELF usingEquals(BiPredicate<? super ACTUAL, ? super ACTUAL> predicate) {
+    return usingEquals(predicate, null);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  @CheckReturnValue
+  public SELF usingEquals(BiPredicate<? super ACTUAL, ? super ACTUAL> predicate, String customEqualsDescription) {
+    return usingComparator((o1, o2) -> predicate.test(o1, o2) ? 0 : -1, customEqualsDescription);
+  }
+
   /** {@inheritDoc} */
   @Override
   @CheckReturnValue
diff --git a/assertj-core/src/main/java/org/assertj/core/api/Assert.java b/assertj-core/src/main/java/org/assertj/core/api/Assert.java
index 7421f5d22..ad68d2f44 100644
--- a/assertj-core/src/main/java/org/assertj/core/api/Assert.java
+++ b/assertj-core/src/main/java/org/assertj/core/api/Assert.java
@@ -15,6 +15,7 @@ package org.assertj.core.api;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.List;
+import java.util.function.BiPredicate;
 import java.util.function.Consumer;
 
 import org.assertj.core.presentation.Representation;
@@ -23,11 +24,10 @@ import org.assertj.core.presentation.StandardRepresentation;
 /**
  * Base contract of all assertion objects: the minimum functionality that any assertion object should provide.
  *
- * @param <SELF> the "self" type of this assertion class. Please read &quot;<a href="http://bit.ly/1IZIRcY"
- *          target="_blank">Emulating
- *          'self types' using Java Generics to simplify fluent API implementation</a>&quot; for more details.
+ * @param <SELF>   the "self" type of this assertion class. Please read &quot;<a href="http://bit.ly/1IZIRcY"
+ *                 target="_blank">Emulating
+ *                 'self types' using Java Generics to simplify fluent API implementation</a>&quot; for more details.
  * @param <ACTUAL> the type of the "actual" value.
- *
  * @author Yvonne Wang
  * @author Alex Ruiz
  * @author Nicolas François
@@ -89,7 +89,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
 
   /**
    * Verifies that the actual value is not {@code null}.
-  * <p>
+   * <p>
    * Example:
    * <pre><code class='java'> // assertions succeed
    * assertThat(&quot;abc&quot;).isNotNull();
@@ -166,7 +166,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * @param values the given array to search the actual value in.
    * @return {@code this} assertion object.
    * @throws NullPointerException if the given array is {@code null}.
-   * @throws AssertionError if the actual value is not present in the given array.
+   * @throws AssertionError       if the actual value is not present in the given array.
    */
   SELF isIn(Object... values);
 
@@ -188,7 +188,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * @param values the given array to search the actual value in.
    * @return {@code this} assertion object.
    * @throws NullPointerException if the given array is {@code null}.
-   * @throws AssertionError if the actual value is present in the given array.
+   * @throws AssertionError       if the actual value is present in the given array.
    */
   SELF isNotIn(Object... values);
 
@@ -210,7 +210,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * @param values the given iterable to search the actual value in.
    * @return {@code this} assertion object.
    * @throws NullPointerException if the given collection is {@code null}.
-   * @throws AssertionError if the actual value is not present in the given iterable.
+   * @throws AssertionError       if the actual value is not present in the given iterable.
    */
   SELF isIn(Iterable<?> values);
 
@@ -232,7 +232,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * @param values the given iterable to search the actual value in.
    * @return {@code this} assertion object.
    * @throws NullPointerException if the given iterable is {@code null}.
-   * @throws AssertionError if the actual value is present in the given iterable.
+   * @throws AssertionError       if the actual value is present in the given iterable.
    */
   SELF isNotIn(Iterable<?> values);
 
@@ -248,15 +248,15 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * assertThat(frodo).usingComparator(raceComparator).isEqualTo(sam);</code></pre>
    *
    * @param customComparator the comparator to use for the incoming assertion checks.
-   * @throws NullPointerException if the given comparator is {@code null}.
    * @return {@code this} assertion object.
+   * @throws NullPointerException if the given comparator is {@code null}.
    */
   SELF usingComparator(Comparator<? super ACTUAL> customComparator);
 
   /**
    * Use the given custom comparator instead of relying on actual type A equals method for incoming assertion checks.
    * <p>
-   * The custom comparator is bound to assertion instance, meaning that if a new assertion instance is created, the default
+   * The custom comparator is bound to the current assertion chain, meaning that if a new assertion instance is created, the default
    * comparison strategy will be used.
    * <p>
    * Examples :
@@ -264,13 +264,48 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * // raceComparator implements Comparator&lt;Character&gt;
    * assertThat(frodo).usingComparator(raceComparator, "Hobbit Race Comparator").isEqualTo(sam);</code></pre>
    *
-   * @param customComparator the comparator to use for the incoming assertion checks.
+   * @param customComparator            the comparator to use for the incoming assertion checks.
    * @param customComparatorDescription comparator description to be used in assertion error messages
-   * @throws NullPointerException if the given comparator is {@code null}.
    * @return {@code this} assertion object.
+   * @throws NullPointerException if the given comparator is {@code null}.
    */
   SELF usingComparator(Comparator<? super ACTUAL> customComparator, String customComparatorDescription);
 
+  /**
+   * Uses the given custom {@link BiPredicate} instead of relying on actual type A {@code equals} method
+   * for incoming assertion checks.
+   * <p>
+   * The custom equals is bound to the current assertion chain, meaning that if a new assertion instance is created, the default
+   * comparison strategy will be used.
+   * <p>
+   * Examples:
+   * <pre><code class='java'> // frodo and sam are instances of Character of Hobbit race (obviously :).
+   * assertThat(frodo).usingEquals((f, s) -> f.race() == s.race()).isEqualTo(sam);</code></pre>
+   *
+   * @param predicate the predicate to use for the incoming assertion checks.
+   * @return {@code this} assertion object.
+   * @throws NullPointerException if the given biPredicate is {@code null}.
+   */
+  SELF usingEquals(BiPredicate<? super ACTUAL, ? super ACTUAL> predicate);
+
+  /**
+   * Uses the given custom {@link BiPredicate} instead of relying on actual type A {@code equals} method
+   * for incoming assertion checks. The given description is present in the assertion error if the assertion fails.
+   * <p>
+   * The custom equals is bound to the current assertion chain, meaning that if a new assertion instance is created, the default
+   * comparison strategy will be used.
+   * <p>
+   * Examples:
+   * <pre><code class='java'> // frodo and sam are instances of Character of Hobbit race (obviously :).
+   * assertThat(frodo).usingEquals((f, s) -> f.race() == s.race(), "comparing race").isEqualTo(sam);</code></pre>
+   *
+   * @param predicate               the predicate to use for the incoming assertion checks.
+   * @param customEqualsDescription comparator description to be used in assertion error messages
+   * @return {@code this} assertion object.
+   * @throws NullPointerException if the given comparator is {@code null}.
+   */
+  SELF usingEquals(BiPredicate<? super ACTUAL, ? super ACTUAL> predicate, String customEqualsDescription);
+
   /**
    * Revert to standard comparison for the incoming assertion checks.
    * <p>
@@ -301,12 +336,10 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    *
    * @param <ASSERT>                the type of the resulting {@code Assert}.
    * @param instanceOfAssertFactory the factory which verifies the type and creates the new {@code Assert}.
-   * @throws NullPointerException if the given factory is {@code null}.
    * @return the narrowed {@code Assert} instance.
-   *
+   * @throws NullPointerException if the given factory is {@code null}.
    * @see InstanceOfAssertFactory
    * @see InstanceOfAssertFactories
-   *
    * @since 3.13.0
    */
   <ASSERT extends AbstractAssert<?, ?>> ASSERT asInstanceOf(InstanceOfAssertFactory<?, ASSERT> instanceOfAssertFactory);
@@ -327,8 +360,8 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * @param type the type to check the actual value against.
    * @return this assertion object.
    * @throws NullPointerException if the given type is {@code null}.
-   * @throws AssertionError if the actual value is {@code null}.
-   * @throws AssertionError if the actual value is not an instance of the given type.
+   * @throws AssertionError       if the actual value is {@code null}.
+   * @throws AssertionError       if the actual value is not an instance of the given type.
    */
   SELF isInstanceOf(Class<?> type);
 
@@ -357,14 +390,14 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * // not a Jedi !
    * assertThat("foo").isInstanceOfSatisfying(Jedi.class, jediRequirements);</code></pre>
    *
-   * @param <T> the generic type to check the actual value against.
-   * @param type the type to check the actual value against.
+   * @param <T>          the generic type to check the actual value against.
+   * @param type         the type to check the actual value against.
    * @param requirements the requirements expressed as a {@link Consumer}.
    * @return this assertion object.
    * @throws NullPointerException if the given type is {@code null}.
    * @throws NullPointerException if the given Consumer is {@code null}.
-   * @throws AssertionError if the actual value is {@code null}.
-   * @throws AssertionError if the actual value is not an instance of the given type.
+   * @throws AssertionError       if the actual value is {@code null}.
+   * @throws AssertionError       if the actual value is not an instance of the given type.
    */
   <T> SELF isInstanceOfSatisfying(Class<T> type, Consumer<T> requirements);
 
@@ -383,8 +416,8 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    *
    * @param types the types to check the actual value against.
    * @return this assertion object.
-   * @throws AssertionError if the actual value is {@code null}.
-   * @throws AssertionError if the actual value is not an instance of any of the given types.
+   * @throws AssertionError       if the actual value is {@code null}.
+   * @throws AssertionError       if the actual value is not an instance of any of the given types.
    * @throws NullPointerException if the given array of types is {@code null}.
    * @throws NullPointerException if the given array of types contains {@code null}s.
    */
@@ -406,8 +439,8 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * @param type the type to check the actual value against.
    * @return this assertion object.
    * @throws NullPointerException if the given type is {@code null}.
-   * @throws AssertionError if the actual value is {@code null}.
-   * @throws AssertionError if the actual value is an instance of the given type.
+   * @throws AssertionError       if the actual value is {@code null}.
+   * @throws AssertionError       if the actual value is an instance of the given type.
    */
   SELF isNotInstanceOf(Class<?> type);
 
@@ -426,8 +459,8 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    *
    * @param types the types to check the actual value against.
    * @return this assertion object.
-   * @throws AssertionError if the actual value is {@code null}.
-   * @throws AssertionError if the actual value is an instance of any of the given types.
+   * @throws AssertionError       if the actual value is {@code null}.
+   * @throws AssertionError       if the actual value is an instance of any of the given types.
    * @throws NullPointerException if the given array of types is {@code null}.
    * @throws NullPointerException if the given array of types contains {@code null}s.
    */
@@ -448,7 +481,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    *
    * @param other the object to check type against.
    * @return this assertion object.
-   * @throws AssertionError if {@code actual} has not the same type as the given object.
+   * @throws AssertionError       if {@code actual} has not the same type as the given object.
    * @throws NullPointerException if the actual value is null.
    * @throws NullPointerException if the given object is null.
    */
@@ -483,7 +516,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * assertThat(wrapper).hasToString("FooWrapper[foo=%s]", foo); </code></pre>
    *
    * @param expectedStringTemplate the format string to use.
-   * @param args the arguments to interpolate into the format string.
+   * @param args                   the arguments to interpolate into the format string.
    * @return this assertion object.
    * @throws AssertionError if {@code actual.toString()} result is not equal to the given {@code String}.
    * @throws AssertionError if actual is {@code null}.
@@ -520,7 +553,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * assertThat(wrapper).doesNotHaveToString("FooBarWrapper[%s]", foo);</code></pre>
    *
    * @param expectedStringTemplate the format string to use.
-   * @param args the arguments to interpolate into the format string.
+   * @param args                   the arguments to interpolate into the format string.
    * @return this assertion object.
    * @throws AssertionError if {@code actual.toString()} result is equal to the given {@code String}.
    * @throws AssertionError if actual is {@code null}.
@@ -543,7 +576,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    *
    * @param other the object to check type against.
    * @return this assertion object.
-   * @throws AssertionError if {@code actual} has the same type as the given object.
+   * @throws AssertionError       if {@code actual} has the same type as the given object.
    * @throws NullPointerException if the actual value is null.
    * @throws NullPointerException if the given object is null.
    */
@@ -565,7 +598,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    *
    * @param type the type to check the actual value against.
    * @return this assertion object.
-   * @throws AssertionError if the actual is not <b>exactly</b> an instance of given type.
+   * @throws AssertionError       if the actual is not <b>exactly</b> an instance of given type.
    * @throws NullPointerException if the actual value is null.
    * @throws NullPointerException if the given object is null.
    */
@@ -587,7 +620,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    *
    * @param type the type to check the actual value against.
    * @return this assertion object.
-   * @throws AssertionError if the actual is exactly an instance of given type.
+   * @throws AssertionError       if the actual is exactly an instance of given type.
    * @throws NullPointerException if the actual value is null.
    * @throws NullPointerException if the given object is null.
    */
@@ -607,7 +640,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    *
    * @param types the types to check the actual value against.
    * @return this assertion object.
-   * @throws AssertionError if the actual value type is not in given type.
+   * @throws AssertionError       if the actual value type is not in given type.
    * @throws NullPointerException if the actual value is null.
    * @throws NullPointerException if the given types is null.
    */
@@ -627,7 +660,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    *
    * @param types the types to check the actual value against.
    * @return this assertion object.
-   * @throws AssertionError if the actual value type is in given types.
+   * @throws AssertionError       if the actual value type is in given types.
    * @throws NullPointerException if the actual value is null.
    * @throws NullPointerException if the given types is null.
    */
@@ -673,10 +706,9 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
   AbstractCharSequenceAssert<?, String> asString();
 
   /**
-   * @deprecated
-   *             Throws <code>{@link UnsupportedOperationException}</code> if called. It is easy to accidentally call
-   *             <code>equals(Object)</code> instead of <code>{@link #isEqualTo(Object)}</code>.
    * @throws UnsupportedOperationException if this method is called.
+   * @deprecated Throws <code>{@link UnsupportedOperationException}</code> if called. It is easy to accidentally call
+   * <code>equals(Object)</code> instead of <code>{@link #isEqualTo(Object)}</code>.
    */
   @Override
   @Deprecated
@@ -687,7 +719,7 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * <p>
    * Example :
    * <pre><code class='java'> assertThat("Messi").withThreadDumpOnError().isEqualTo("Ronaldo");</code></pre>
-   *
+   * <p>
    * will print a thread dump, something similar to this:
    * <pre>{@code "JDWP Command Reader"
    * 	java.lang.Thread.State: RUNNABLE
@@ -793,13 +825,10 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * assertThat(&quot;The Force&quot;).hasSameHashCodeAs(&quot;Awakens&quot;);</code></pre>
    *
    * @param other the object to check hashCode against.
-   *
    * @return this assertion object.
-   *
-   * @throws AssertionError if the actual object is null.
+   * @throws AssertionError       if the actual object is null.
    * @throws NullPointerException if the other object is null.
-   * @throws AssertionError if the actual object has not the same hashCode as the given object.
-   *
+   * @throws AssertionError       if the actual object has not the same hashCode as the given object.
    * @since 2.9.0
    */
   SELF hasSameHashCodeAs(Object other);
@@ -818,13 +847,10 @@ public interface Assert<SELF extends Assert<SELF, ACTUAL>, ACTUAL> extends Descr
    * assertThat(new Jedi(&quot;Yoda&quot;, &quot;Blue&quot;)).doesNotHaveSameHashCodeAs(new Jedi(&quot;Yoda&quot;, &quot;Blue&quot;)); </code></pre>
    *
    * @param other the object to check hashCode against.
-   *
    * @return this assertion object.
-   *
-   * @throws AssertionError if the actual object is null.
+   * @throws AssertionError       if the actual object is null.
    * @throws NullPointerException if the other object is null.
-   * @throws AssertionError if the actual object has the same hashCode as the given object.
-   *
+   * @throws AssertionError       if the actual object has the same hashCode as the given object.
    * @since 3.19.0
    */
   SELF doesNotHaveSameHashCodeAs(Object other);


Test patch:
diff --git a/assertj-core/src/test/java/org/assertj/core/api/object/ObjectAssert_usingEquals_Test.java b/assertj-core/src/test/java/org/assertj/core/api/object/ObjectAssert_usingEquals_Test.java
new file mode 100644
index 000000000..8d30a1a75
--- /dev/null
+++ b/assertj-core/src/test/java/org/assertj/core/api/object/ObjectAssert_usingEquals_Test.java
@@ -0,0 +1,66 @@
+/*
+ * 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
+ *
+ * http://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.
+ *
+ * Copyright 2012-2024 the original author or authors.
+ */
+package org.assertj.core.api.object;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.BDDAssertions.then;
+import static org.assertj.core.testkit.BiPredicates.ALWAYS_DIFFERENT;
+import static org.assertj.core.testkit.BiPredicates.ALWAYS_EQUALS;
+import static org.assertj.core.util.AssertionsUtil.expectAssertionError;
+
+import org.assertj.core.testkit.Jedi;
+import org.junit.jupiter.api.Test;
+
+class ObjectAssert_usingEquals_Test {
+
+  @Test
+  void should_be_able_to_use_a_custom_equals_comparison() {
+    // GIVEN
+    Jedi yoda = new Jedi("Yoda", "green");
+    Jedi luke = new Jedi("Luke", "green");
+    // WHEN/THEN
+    then(yoda).usingEquals(ALWAYS_EQUALS).isEqualTo(luke);
+    then(yoda).usingEquals(ALWAYS_EQUALS, "always equals").isEqualTo(luke);
+    then(yoda).usingEquals(ALWAYS_DIFFERENT).isNotEqualTo(luke);
+    then(yoda).usingEquals(ALWAYS_DIFFERENT, "always different").isNotEqualTo(luke);
+  }
+
+  @Test
+  void should_include_custom_equals_description_in_error_message() {
+    // GIVEN
+    Jedi yoda = new Jedi("Yoda", "green");
+    Jedi luke = new Jedi("Luke", "green");
+    // WHEN
+    AssertionError assertionError = expectAssertionError(() -> assertThat(yoda).usingEquals((o1, o2) -> o1.getName()
+                                                                                                          .equals(o2.getName()),
+                                                                                            "comparing names")
+                                                                               .isEqualTo(luke));
+    // THEN
+    then(assertionError).hasMessageContaining("comparing names");
+  }
+
+  @Test
+  void should_reset_custom_equals_to_default() {
+    // GIVEN
+    Jedi yoda1 = new Jedi("Yoda", "green");
+    Jedi yoda2 = new Jedi("Yoda", "green");
+    // WHEN/THEN
+    then(yoda1).usingEquals(ALWAYS_DIFFERENT)
+               .usingDefaultComparator()
+               .isEqualTo(yoda2);
+    then(yoda2).usingEquals(ALWAYS_DIFFERENT, "always different")
+               .usingDefaultComparator()
+               .isEqualTo(yoda1);
+  }
+
+}