diff --git a/assertj-core/src/main/java/org/assertj/core/error/ShouldBeEqual.java b/assertj-core/src/main/java/org/assertj/core/error/ShouldBeEqual.java
index f0510b6bf1..f0650b2f9c 100644
--- a/assertj-core/src/main/java/org/assertj/core/error/ShouldBeEqual.java
+++ b/assertj-core/src/main/java/org/assertj/core/error/ShouldBeEqual.java
@@ -28,6 +28,7 @@
import org.assertj.core.internal.StandardComparisonStrategy;
import org.assertj.core.presentation.Representation;
import org.assertj.core.util.VisibleForTesting;
+import org.assertj.core.util.introspection.ClassUtils;
/**
* Creates an {@link AssertionError}
indicating that an assertion that verifies that two objects are equal
@@ -195,18 +196,20 @@ protected String indent(String valueRepresentation) {
}
/**
- * Builds and returns an error message from description using {@link #detailedExpected()} and
- * {@link #detailedActual()} detailed representation.
+ * Builds and returns an error message from description using {@link #detailedExpected(boolean)} and
+ * {@link #detailedActual(boolean)} detailed representation.
*
* @param description the {@link Description} used to build the returned error message
* @param representation the {@link org.assertj.core.presentation.Representation} used to build String representation
* of object
- * @return the error message from description using {@link #detailedExpected()} and {@link #detailedActual()}
+ * @return the error message from description using {@link #detailedExpected(boolean)} and {@link #detailedActual(boolean)}
* detailed representation.
*/
protected String defaultDetailedErrorMessage(Description description, Representation representation) {
- String actualRepresentation = detailedActual();
- String expectedRepresentation = detailedExpected();
+ boolean sameClassNameInDifferentPackages = ClassUtils.areClassesWithSameNameInDifferentPackages(actual.getClass(),
+ expected.getClass());
+ String actualRepresentation = detailedActual(sameClassNameInDifferentPackages);
+ String expectedRepresentation = detailedExpected(sameClassNameInDifferentPackages);
if (hasMultilineValue(actualRepresentation, expectedRepresentation)) {
return errorMessageForMultilineValues(description, representation, actualRepresentation, expectedRepresentation);
}
@@ -255,12 +258,12 @@ private AssertionError newComparisonFailure(String description) throws Exception
return o instanceof AssertionError ? (AssertionError) o : null;
}
- protected String detailedActual() {
- return representation.unambiguousToStringOf(actual);
+ protected String detailedActual(boolean sameClassWithDifferentPackages) {
+ return representation.unambiguousToStringOf(actual, sameClassWithDifferentPackages);
}
- protected String detailedExpected() {
- return representation.unambiguousToStringOf(expected);
+ protected String detailedExpected(boolean sameClassWithDifferentPackages) {
+ return representation.unambiguousToStringOf(expected, sameClassWithDifferentPackages);
}
@Override
diff --git a/assertj-core/src/main/java/org/assertj/core/internal/UnambiguousRepresentation.java b/assertj-core/src/main/java/org/assertj/core/internal/UnambiguousRepresentation.java
index abe5609533..1e7d0dcda2 100644
--- a/assertj-core/src/main/java/org/assertj/core/internal/UnambiguousRepresentation.java
+++ b/assertj-core/src/main/java/org/assertj/core/internal/UnambiguousRepresentation.java
@@ -19,7 +19,7 @@
/**
* Utility class around {@link Representation} to provide the {@link Representation#toStringOf(Object) toStringOf}
* representations of {@code actual} and {@code expected} when they are different, and their
- * {@link Representation#unambiguousToStringOf(Object) unambiguousToStringOf} representations if not.
+ * {@link Representation#unambiguousToStringOf(Object, boolean) unambiguousToStringOf} representations if not.
*/
public class UnambiguousRepresentation {
@@ -33,10 +33,10 @@ public UnambiguousRepresentation(Representation representation, Object actual, O
boolean sameRepresentation = Objects.equals(actualRepresentation, expectedRepresentation);
this.actual = sameRepresentation
- ? representation.unambiguousToStringOf(actual)
+ ? representation.unambiguousToStringOf(actual, false)
: actualRepresentation;
this.expected = sameRepresentation
- ? representation.unambiguousToStringOf(expected)
+ ? representation.unambiguousToStringOf(expected, false)
: expectedRepresentation;
}
diff --git a/assertj-core/src/main/java/org/assertj/core/presentation/CompositeRepresentation.java b/assertj-core/src/main/java/org/assertj/core/presentation/CompositeRepresentation.java
index 7c2af9b9a8..5f406ce004 100644
--- a/assertj-core/src/main/java/org/assertj/core/presentation/CompositeRepresentation.java
+++ b/assertj-core/src/main/java/org/assertj/core/presentation/CompositeRepresentation.java
@@ -41,13 +41,13 @@ public String toStringOf(Object object) {
}
@Override
- public String unambiguousToStringOf(Object object) {
+ public String unambiguousToStringOf(Object object, boolean shouldKeepPackage) {
// don't create streams for performance reasons and because this code is simple enough (even not as elegant as with stream)
for (Representation representation : representations) {
- String value = representation.unambiguousToStringOf(object);
+ String value = representation.unambiguousToStringOf(object, shouldKeepPackage);
if (value != null) return value;
}
- return STANDARD_REPRESENTATION.unambiguousToStringOf(object);
+ return STANDARD_REPRESENTATION.unambiguousToStringOf(object, shouldKeepPackage);
}
@Override
diff --git a/assertj-core/src/main/java/org/assertj/core/presentation/Representation.java b/assertj-core/src/main/java/org/assertj/core/presentation/Representation.java
index c876af310d..afbdc51700 100644
--- a/assertj-core/src/main/java/org/assertj/core/presentation/Representation.java
+++ b/assertj-core/src/main/java/org/assertj/core/presentation/Representation.java
@@ -65,16 +65,17 @@ public interface Representation {
String toStringOf(Object object);
/**
- * Override this method to return a {@code String} representation of the given object that is unambigous so that it can
+ * Override this method to return a {@code String} representation of the given object that is unambigous so that it can
* be differentiated from other objects with the same {@link #toStringOf(Object)} representation.
*
- * The default implementation calls {@link #toStringOf(Object)} but the {@link StandardRepresentation} adds - * the object hexadecimal identity hash code. + * The default implementation calls {@link #toStringOf(Object)} but the {@link StandardRepresentation} adds + * the object hexadecimal identity hash code. * - * @param object the object to represent. + * @param object the object to represent. + * @param shouldKeepPackage if we should display the object's package * @return the unambiguous {@code toString} representation of the given object. */ - default String unambiguousToStringOf(Object object) { + default String unambiguousToStringOf(Object object, boolean shouldKeepPackage) { return toStringOf(object); } diff --git a/assertj-core/src/main/java/org/assertj/core/presentation/StandardRepresentation.java b/assertj-core/src/main/java/org/assertj/core/presentation/StandardRepresentation.java index 57de0b4121..0a0df863ae 100644 --- a/assertj-core/src/main/java/org/assertj/core/presentation/StandardRepresentation.java +++ b/assertj-core/src/main/java/org/assertj/core/presentation/StandardRepresentation.java @@ -297,14 +297,21 @@ private static boolean hasOverriddenToStringInSubclassOf(Class> objectClass, C * Returns the {@code String} representation of the given object with its type and hexadecimal identity hash code so that * it can be differentiated from other objects with the same {@link #toStringOf(Object)} representation. * - * @param obj the object to represent. + * @param obj the object to represent. + * @param shouldKeepPackage * @return the unambiguous {@code toString} representation of the given object. */ @Override - public String unambiguousToStringOf(Object obj) { + public String unambiguousToStringOf(Object obj, boolean shouldKeepPackage) { + if (obj == null) return null; // some types have already an unambiguous toString, no need to double down if (hasAlreadyAnUnambiguousToStringOf(obj)) return toStringOf(obj); - return obj == null ? null : String.format("%s (%s@%s)", toStringOf(obj), classNameOf(obj), identityHexCodeOf(obj)); + return obj == null ? null + : String.format("%s (%s@%s)", toStringOf(obj), getObject(obj, shouldKeepPackage), identityHexCodeOf(obj)); + } + + private Object getObject(Object obj, boolean shouldKeepPackage) { + return shouldKeepPackage ? packageAndClassNameOf(obj) : classNameOf(obj); } @Override @@ -740,6 +747,10 @@ private static Object classNameOf(Object obj) { return obj.getClass().isAnonymousClass() ? obj.getClass().getName() : obj.getClass().getSimpleName(); } + private static Object packageAndClassNameOf(Object obj) { + return String.format("%s.%s", obj.getClass().getPackageName(), classNameOf(obj)); + } + private String defaultToStringWithClassNameDisambiguation(Object o) { return o.toString() + classNameDisambiguation(o); } diff --git a/assertj-core/src/main/java/org/assertj/core/util/introspection/ClassUtils.java b/assertj-core/src/main/java/org/assertj/core/util/introspection/ClassUtils.java index 4590b5707c..ad6e7f9193 100644 --- a/assertj-core/src/main/java/org/assertj/core/util/introspection/ClassUtils.java +++ b/assertj-core/src/main/java/org/assertj/core/util/introspection/ClassUtils.java @@ -145,4 +145,17 @@ public static boolean isOptionalOrPrimitiveOptional(final Class> type) { public static boolean isInJavaLangPackage(final Class> type) { return type != null && type.getName().startsWith("java.lang"); } + + /** + * Returns whether the given {@code type1} and {@code type2} have the same name but are + * located in different packages + * + * @param type1 first class to compare + * @param type2 the class to compare to + * @return true if the given {@code type1} have the same name as {@code type2} but is + * in a different package + */ + public static boolean areClassesWithSameNameInDifferentPackages(Class> type1, Class> type2) { + return type1.getSimpleName().equals(type2.getSimpleName()) && !type1.getPackageName().equals(type2.getPackageName()); + } } diff --git a/assertj-core/src/test/java/org/assertj/core/internal/UnambiguousRepresentation_Test.java b/assertj-core/src/test/java/org/assertj/core/internal/UnambiguousRepresentation_Test.java index 52f90da28d..a96a0a114f 100644 --- a/assertj-core/src/test/java/org/assertj/core/internal/UnambiguousRepresentation_Test.java +++ b/assertj-core/src/test/java/org/assertj/core/internal/UnambiguousRepresentation_Test.java @@ -53,8 +53,8 @@ void should_use_unambiguousToStringOf_whe_toStringOf_are_equal() { Object expected = new Object(); given(representation.toStringOf(actual)).willReturn("representation"); given(representation.toStringOf(expected)).willReturn("representation"); - given(representation.unambiguousToStringOf(actual)).willReturn("actual"); - given(representation.unambiguousToStringOf(expected)).willReturn("expected"); + given(representation.unambiguousToStringOf(actual, false)).willReturn("actual"); + given(representation.unambiguousToStringOf(expected, false)).willReturn("expected"); // WHEN UnambiguousRepresentation actualRepresentation = new UnambiguousRepresentation(representation, actual, expected); // THEN diff --git a/assertj-core/src/test/java/org/assertj/core/presentation/CompositeRepresentation_Test.java b/assertj-core/src/test/java/org/assertj/core/presentation/CompositeRepresentation_Test.java index c03050d0fc..925b88de9e 100644 --- a/assertj-core/src/test/java/org/assertj/core/presentation/CompositeRepresentation_Test.java +++ b/assertj-core/src/test/java/org/assertj/core/presentation/CompositeRepresentation_Test.java @@ -34,7 +34,7 @@ void should_use_representation_with_highest_priority() { CompositeRepresentation compositeRepresentation = new CompositeRepresentation(representations); // WHEN String toString = compositeRepresentation.toStringOf("foo"); - String unambiguousToString = compositeRepresentation.unambiguousToStringOf("foo"); + String unambiguousToString = compositeRepresentation.unambiguousToStringOf("foo", false); // THEN then(toString).isEqualTo("3"); then(unambiguousToString).isEqualTo("3"); @@ -48,7 +48,9 @@ void should_use_standard_representation_if_composite_representation_is_not_given Object longNumber = 123L; // THEN then(compositeRepresentation.toStringOf(longNumber)).isEqualTo(STANDARD_REPRESENTATION.toStringOf(longNumber)); - then(compositeRepresentation.unambiguousToStringOf(longNumber)).isEqualTo(STANDARD_REPRESENTATION.unambiguousToStringOf(longNumber)); + then(compositeRepresentation.unambiguousToStringOf(longNumber, + false)).isEqualTo(STANDARD_REPRESENTATION.unambiguousToStringOf(longNumber, + false)); } @Test @@ -86,7 +88,7 @@ public int getPriority() { } @Override - public String unambiguousToStringOf(Object object) { + public String unambiguousToStringOf(Object object, boolean shouldKeepPackage) { return "" + getPriority(); } diff --git a/assertj-core/src/test/java/org/assertj/core/presentation/StandardRepresentation_unambiguousToStringOf_Test.java b/assertj-core/src/test/java/org/assertj/core/presentation/StandardRepresentation_unambiguousToStringOf_Test.java index 88d44ec8d1..c03bbeb11b 100644 --- a/assertj-core/src/test/java/org/assertj/core/presentation/StandardRepresentation_unambiguousToStringOf_Test.java +++ b/assertj-core/src/test/java/org/assertj/core/presentation/StandardRepresentation_unambiguousToStringOf_Test.java @@ -48,7 +48,7 @@ import org.junit.jupiter.api.Test; /** - * Tests for {@link StandardRepresentation#unambiguousToStringOf(Object)}. + * Tests for {@link Representation#unambiguousToStringOf(Object, boolean)}. * * @author Alexandre Dutra */ @@ -405,8 +405,34 @@ void isEqualTo_should_show_disambiguated_objects_with_same_hash_code_and_toStrin .hasMessageContaining(unambiguousToStringOf(ambiguous2)); } + @Test + void should_get_unambiguous_representation_with_package() { + // GIVEN + Person person = new Person(); + boolean shouldKeepPackageName = true; + + // WHEN + String unambiguousRepresentation = STANDARD_REPRESENTATION.unambiguousToStringOf(person, shouldKeepPackageName); + + // THEN + assertThat(unambiguousRepresentation).isEqualTo("Person [name=null, age=0, account=0] (org.assertj.core.presentation.Person@3d299e3)"); + } + + @Test + void should_get_unambiguous_representation_without_package() { + // GIVEN + Person person = new Person(); + boolean shouldKeepPackageName = false; + + // WHEN + String unambiguousRepresentation = STANDARD_REPRESENTATION.unambiguousToStringOf(person, shouldKeepPackageName); + + // THEN + assertThat(unambiguousRepresentation).isEqualTo("Person [name=null, age=0, account=0] (Person@3d299e3)"); + } + private static String unambiguousToStringOf(Object o) { - return STANDARD_REPRESENTATION.unambiguousToStringOf(o); + return STANDARD_REPRESENTATION.unambiguousToStringOf(o, false); } private static class MyTestFile extends File { diff --git a/assertj-core/src/test/java/org/assertj/core/util/introspection/ClassUtils_areSameClassInDifferentPackages_Test.java b/assertj-core/src/test/java/org/assertj/core/util/introspection/ClassUtils_areSameClassInDifferentPackages_Test.java new file mode 100644 index 0000000000..49becdf890 --- /dev/null +++ b/assertj-core/src/test/java/org/assertj/core/util/introspection/ClassUtils_areSameClassInDifferentPackages_Test.java @@ -0,0 +1,35 @@ +package org.assertj.core.util.introspection; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.BDDAssertions.then; + +class ClassUtils_areSameClassInDifferentPackages_Test { + + @Test + void areClassesWithSameNameInDifferentPackages() { + // WHEN + boolean areSameClassInDifferentPackages = ClassUtils.areClassesWithSameNameInDifferentPackages(java.util.Date.class, + java.sql.Date.class); + // THEN + then(areSameClassInDifferentPackages).isTrue(); + } + + @Test + void areClassesWithSameNameInDifferentPackagesForSameClass() { + // WHEN + boolean areSameClassInDifferentPackages = ClassUtils.areClassesWithSameNameInDifferentPackages(java.util.Date.class, + java.util.Date.class); + // THEN + then(areSameClassInDifferentPackages).isFalse(); + } + + @Test + void areNotClassesWithSameNameInDifferentPackages() { + // WHEN + boolean areSameClassInDifferentPackages = ClassUtils.areClassesWithSameNameInDifferentPackages(java.util.Date.class, + java.text.DateFormat.class); + // THEN + then(areSameClassInDifferentPackages).isFalse(); + } +}