diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertArrayEquals.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertArrayEquals.java index 0f28b904e663..2a2f8f6d2042 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertArrayEquals.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertArrayEquals.java @@ -10,11 +10,8 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; -import static org.junit.jupiter.api.AssertionUtils.fail; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.formatIndexes; -import static org.junit.jupiter.api.AssertionUtils.formatValues; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; import static org.junit.platform.commons.util.ReflectionUtils.isArray; import java.util.ArrayDeque; @@ -406,30 +403,41 @@ private static void assertArraysNotNull(Object expected, Object actual, Deque indexes, Object messageOrSupplier) { - fail(buildPrefix(nullSafeGet(messageOrSupplier)) + "expected array was " + formatIndexes(indexes)); + assertionFailure() // + .message(messageOrSupplier) // + .reason("expected array was " + formatIndexes(indexes)) // + .buildAndThrow(); } private static void failActualArrayIsNull(Deque indexes, Object messageOrSupplier) { - fail(buildPrefix(nullSafeGet(messageOrSupplier)) + "actual array was " + formatIndexes(indexes)); + assertionFailure() // + .message(messageOrSupplier) // + .reason("actual array was " + formatIndexes(indexes)) // + .buildAndThrow(); } private static void assertArraysHaveSameLength(int expected, int actual, Deque indexes, Object messageOrSupplier) { if (expected != actual) { - String prefix = buildPrefix(nullSafeGet(messageOrSupplier)); - String message = "array lengths differ" + formatIndexes(indexes) + ", expected: <" + expected - + "> but was: <" + actual + ">"; - fail(prefix + message); + assertionFailure() // + .message(messageOrSupplier) // + .reason("array lengths differ" + formatIndexes(indexes)) // + .expected(expected) // + .actual(actual) // + .buildAndThrow(); } } private static void failArraysNotEqual(Object expected, Object actual, Deque indexes, Object messageOrSupplier) { - String prefix = buildPrefix(nullSafeGet(messageOrSupplier)); - String message = "array contents differ" + formatIndexes(indexes) + ", " + formatValues(expected, actual); - fail(prefix + message); + assertionFailure() // + .message(messageOrSupplier) // + .reason("array contents differ" + formatIndexes(indexes)) // + .expected(expected) // + .actual(actual) // + .buildAndThrow(); } private static Deque nullSafeIndexes(Deque indexes, int newIndex) { diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertDoesNotThrow.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertDoesNotThrow.java index e64b136772ff..d11a3e0e6dbf 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertDoesNotThrow.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertDoesNotThrow.java @@ -10,8 +10,7 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.Supplier; @@ -78,9 +77,11 @@ private static T assertDoesNotThrow(ThrowingSupplier supplier, Object mes } private static AssertionFailedError createAssertionFailedError(Object messageOrSupplier, Throwable t) { - String message = buildPrefix(nullSafeGet(messageOrSupplier)) + "Unexpected exception thrown: " - + t.getClass().getName() + buildSuffix(t.getMessage()); - return new AssertionFailedError(message, t); + return assertionFailure() // + .message(messageOrSupplier) // + .reason("Unexpected exception thrown: " + t.getClass().getName() + buildSuffix(t.getMessage())) // + .cause(t) // + .build(); } private static String buildSuffix(String message) { diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertEquals.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertEquals.java index 8a06b335599c..9afd4b1072c5 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertEquals.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertEquals.java @@ -10,8 +10,8 @@ package org.junit.jupiter.api; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.doublesAreEqual; -import static org.junit.jupiter.api.AssertionUtils.failNotEqual; import static org.junit.jupiter.api.AssertionUtils.floatsAreEqual; import static org.junit.jupiter.api.AssertionUtils.objectsAreEqual; @@ -189,4 +189,11 @@ static void assertEquals(Object expected, Object actual, Supplier messag } } + private static void failNotEqual(Object expected, Object actual, Object messageOrSupplier) { + assertionFailure() // + .message(messageOrSupplier) // + .expected(expected) // + .actual(actual) // + .buildAndThrow(); + } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertFalse.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertFalse.java index 604c26e98af6..8364cb64615b 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertFalse.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertFalse.java @@ -10,9 +10,7 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; -import static org.junit.jupiter.api.AssertionUtils.fail; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.BooleanSupplier; import java.util.function.Supplier; @@ -25,8 +23,6 @@ */ class AssertFalse { - private static final String EXPECTED_FALSE = "expected: but was: "; - private AssertFalse() { /* no-op */ } @@ -37,13 +33,13 @@ static void assertFalse(boolean condition) { static void assertFalse(boolean condition, String message) { if (condition) { - fail(buildPrefix(message) + EXPECTED_FALSE, false, true); + failNotFalse(message); } } static void assertFalse(boolean condition, Supplier messageSupplier) { if (condition) { - fail(buildPrefix(nullSafeGet(messageSupplier)) + EXPECTED_FALSE, false, true); + failNotFalse(messageSupplier); } } @@ -59,4 +55,12 @@ static void assertFalse(BooleanSupplier booleanSupplier, Supplier messag assertFalse(booleanSupplier.getAsBoolean(), messageSupplier); } + private static void failNotFalse(Object messageOrSupplier) { + assertionFailure() // + .message(messageOrSupplier) // + .expected(false) // + .actual(true) // + .buildAndThrow(); + } + } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertInstanceOf.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertInstanceOf.java index fd491bc25c0c..f1891d138c83 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertInstanceOf.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertInstanceOf.java @@ -10,14 +10,10 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; -import static org.junit.jupiter.api.AssertionUtils.format; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.Supplier; -import org.opentest4j.AssertionFailedError; - /** * {@code AssertInstanceOf} is a collection of utility methods that support * asserting that an object is of an expected type — in other words, if it @@ -45,10 +41,12 @@ static T assertInstanceOf(Class expectedType, Object actualValue, Supplie private static T assertInstanceOf(Class expectedType, Object actualValue, Object messageOrSupplier) { if (!expectedType.isInstance(actualValue)) { - String reason = (actualValue == null ? "Unexpected null value" : "Unexpected type"); - String message = buildPrefix(nullSafeGet(messageOrSupplier)) - + format(expectedType, actualValue == null ? null : actualValue.getClass(), reason); - throw new AssertionFailedError(message); + assertionFailure() // + .message(messageOrSupplier) // + .reason(actualValue == null ? "Unexpected null value" : "Unexpected type") // + .expected(expectedType) // + .actual(actualValue == null ? null : actualValue.getClass()) // + .buildAndThrow(); } return expectedType.cast(actualValue); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java index dd581398d4d6..a569d2105b90 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java @@ -10,11 +10,8 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; -import static org.junit.jupiter.api.AssertionUtils.fail; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.formatIndexes; -import static org.junit.jupiter.api.AssertionUtils.formatValues; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; import java.util.ArrayDeque; import java.util.Deque; @@ -139,11 +136,17 @@ private static void assertIterablesNotNull(Object expected, Object actual, Deque } private static void failExpectedIterableIsNull(Deque indexes, Object messageOrSupplier) { - fail(buildPrefix(nullSafeGet(messageOrSupplier)) + "expected iterable was " + formatIndexes(indexes)); + assertionFailure() // + .message(messageOrSupplier) // + .reason("expected iterable was " + formatIndexes(indexes)) // + .buildAndThrow(); } private static void failActualIterableIsNull(Deque indexes, Object messageOrSupplier) { - fail(buildPrefix(nullSafeGet(messageOrSupplier)) + "actual iterable was " + formatIndexes(indexes)); + assertionFailure() // + .message(messageOrSupplier) // + .reason("actual iterable was " + formatIndexes(indexes)) // + .buildAndThrow(); } private static void assertIteratorsAreEmpty(Iterator expected, Iterator actual, int processed, @@ -156,19 +159,24 @@ private static void assertIteratorsAreEmpty(Iterator expected, Iterator ac AtomicInteger actualCount = new AtomicInteger(processed); actual.forEachRemaining(e -> actualCount.incrementAndGet()); - String prefix = buildPrefix(nullSafeGet(messageOrSupplier)); - String message = "iterable lengths differ" + formatIndexes(indexes) + ", expected: <" + expectedCount.get() - + "> but was: <" + actualCount.get() + ">"; - fail(prefix + message); + assertionFailure() // + .message(messageOrSupplier) // + .reason("iterable lengths differ" + formatIndexes(indexes)) // + .expected(expectedCount.get()) // + .actual(actualCount.get()) // + .buildAndThrow(); } } private static void failIterablesNotEqual(Object expected, Object actual, Deque indexes, Object messageOrSupplier) { - String prefix = buildPrefix(nullSafeGet(messageOrSupplier)); - String message = "iterable contents differ" + formatIndexes(indexes) + ", " + formatValues(expected, actual); - fail(prefix + message); + assertionFailure() // + .message(messageOrSupplier) // + .reason("iterable contents differ" + formatIndexes(indexes)) // + .expected(expected) // + .actual(actual) // + .buildAndThrow(); } private final static class Pair { diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java index 8b55d54d12e2..1479728830ed 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java @@ -12,8 +12,7 @@ import static java.lang.String.format; import static java.lang.String.join; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.platform.commons.util.Preconditions.condition; import static org.junit.platform.commons.util.Preconditions.notNull; @@ -195,8 +194,13 @@ String snippet(String line) { void fail(String format, Object... args) { String newLine = System.lineSeparator(); - String message = buildPrefix(nullSafeGet(messageOrSupplier)) + format(format, args); - AssertionUtils.fail(message, join(newLine, expectedLines), join(newLine, actualLines)); + assertionFailure() // + .message(messageOrSupplier) // + .reason(format(format, args)) // + .expected(join(newLine, expectedLines)) // + .actual(join(newLine, actualLines)) // + .includeValuesInMessage(false) // + .buildAndThrow(); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotEquals.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotEquals.java index 3bdb087dd9f6..1e8be26c6a5e 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotEquals.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotEquals.java @@ -10,11 +10,9 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.doublesAreEqual; -import static org.junit.jupiter.api.AssertionUtils.fail; import static org.junit.jupiter.api.AssertionUtils.floatsAreEqual; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; import static org.junit.jupiter.api.AssertionUtils.objectsAreEqual; import java.util.function.Supplier; @@ -52,7 +50,7 @@ static void assertNotEquals(byte unexpected, byte actual, String message) { */ static void assertNotEquals(byte unexpected, byte actual, Supplier messageSupplier) { if (unexpected == actual) { - failEqual(actual, nullSafeGet(messageSupplier)); + failEqual(actual, messageSupplier); } } @@ -77,7 +75,7 @@ static void assertNotEquals(short unexpected, short actual, String message) { */ static void assertNotEquals(short unexpected, short actual, Supplier messageSupplier) { if (unexpected == actual) { - failEqual(actual, nullSafeGet(messageSupplier)); + failEqual(actual, messageSupplier); } } @@ -102,7 +100,7 @@ static void assertNotEquals(int unexpected, int actual, String message) { */ static void assertNotEquals(int unexpected, int actual, Supplier messageSupplier) { if (unexpected == actual) { - failEqual(actual, nullSafeGet(messageSupplier)); + failEqual(actual, messageSupplier); } } @@ -127,7 +125,7 @@ static void assertNotEquals(long unexpected, long actual, String message) { */ static void assertNotEquals(long unexpected, long actual, Supplier messageSupplier) { if (unexpected == actual) { - failEqual(actual, nullSafeGet(messageSupplier)); + failEqual(actual, messageSupplier); } } @@ -152,7 +150,7 @@ static void assertNotEquals(float unexpected, float actual, String message) { */ static void assertNotEquals(float unexpected, float actual, Supplier messageSupplier) { if (floatsAreEqual(unexpected, actual)) { - failEqual(actual, nullSafeGet(messageSupplier)); + failEqual(actual, messageSupplier); } } @@ -177,7 +175,7 @@ static void assertNotEquals(float unexpected, float actual, float delta, String */ static void assertNotEquals(float unexpected, float actual, float delta, Supplier messageSupplier) { if (floatsAreEqual(unexpected, actual, delta)) { - failEqual(actual, nullSafeGet(messageSupplier)); + failEqual(actual, messageSupplier); } } @@ -202,7 +200,7 @@ static void assertNotEquals(double unexpected, double actual, String message) { */ static void assertNotEquals(double unexpected, double actual, Supplier messageSupplier) { if (doublesAreEqual(unexpected, actual)) { - failEqual(actual, nullSafeGet(messageSupplier)); + failEqual(actual, messageSupplier); } } @@ -227,7 +225,7 @@ static void assertNotEquals(double unexpected, double actual, double delta, Stri */ static void assertNotEquals(double unexpected, double actual, double delta, Supplier messageSupplier) { if (doublesAreEqual(unexpected, actual, delta)) { - failEqual(actual, nullSafeGet(messageSupplier)); + failEqual(actual, messageSupplier); } } @@ -252,7 +250,7 @@ static void assertNotEquals(char unexpected, char actual, String message) { */ static void assertNotEquals(char unexpected, char actual, Supplier messageSupplier) { if (unexpected == actual) { - failEqual(actual, nullSafeGet(messageSupplier)); + failEqual(actual, messageSupplier); } } @@ -268,12 +266,15 @@ static void assertNotEquals(Object unexpected, Object actual, String message) { static void assertNotEquals(Object unexpected, Object actual, Supplier messageSupplier) { if (objectsAreEqual(unexpected, actual)) { - failEqual(actual, nullSafeGet(messageSupplier)); + failEqual(actual, messageSupplier); } } - private static void failEqual(Object actual, String message) { - fail(buildPrefix(message) + "expected: not equal but was: <" + actual + ">"); + private static void failEqual(Object actual, Object messageOrSupplier) { + assertionFailure() // + .message(messageOrSupplier) // + .reason("expected: not equal but was: <" + actual + ">") // + .buildAndThrow(); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotNull.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotNull.java index eebd9329cf4a..71be7b88a72f 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotNull.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotNull.java @@ -10,8 +10,7 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.Supplier; @@ -39,11 +38,14 @@ static void assertNotNull(Object actual, String message) { static void assertNotNull(Object actual, Supplier messageSupplier) { if (actual == null) { - failNull(nullSafeGet(messageSupplier)); + failNull(messageSupplier); } } - private static void failNull(String message) { - Assertions.fail(buildPrefix(message) + "expected: not "); + private static void failNull(Object messageOrSupplier) { + assertionFailure() // + .message(messageOrSupplier) // + .reason("expected: not ") // + .buildAndThrow(); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotSame.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotSame.java index a3652c39292e..753e734c2a34 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotSame.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotSame.java @@ -10,9 +10,7 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; -import static org.junit.jupiter.api.AssertionUtils.fail; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.Supplier; @@ -40,12 +38,15 @@ static void assertNotSame(Object unexpected, Object actual, String message) { static void assertNotSame(Object unexpected, Object actual, Supplier messageSupplier) { if (unexpected == actual) { - failSame(actual, nullSafeGet(messageSupplier)); + failSame(actual, messageSupplier); } } - private static void failSame(Object actual, String message) { - fail(buildPrefix(message) + "expected: not same but was: <" + actual + ">"); + private static void failSame(Object actual, Object messageOrSupplier) { + assertionFailure() // + .message(messageOrSupplier) // + .reason("expected: not same but was: <" + actual + ">") // + .buildAndThrow(); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNull.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNull.java index b3a43b24844f..4a9e92b2d4a0 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNull.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNull.java @@ -10,10 +10,7 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; -import static org.junit.jupiter.api.AssertionUtils.fail; -import static org.junit.jupiter.api.AssertionUtils.format; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.Supplier; @@ -41,18 +38,16 @@ static void assertNull(Object actual, String message) { static void assertNull(Object actual, Supplier messageSupplier) { if (actual != null) { - failNotNull(actual, nullSafeGet(messageSupplier)); + failNotNull(actual, messageSupplier); } } - private static void failNotNull(Object actual, String message) { - String stringRepresentation = actual.toString(); - if (stringRepresentation == null || stringRepresentation.equals("null")) { - fail(format(null, actual, message), null, actual); - } - else { - fail(buildPrefix(message) + "expected: but was: <" + actual + ">", null, actual); - } + private static void failNotNull(Object actual, Object messageOrSupplier) { + assertionFailure() // + .message(messageOrSupplier) // + .expected(null) // + .actual(actual) // + .buildAndThrow(); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertSame.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertSame.java index 6f8a790dc237..c080b3e01f65 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertSame.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertSame.java @@ -10,9 +10,7 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.fail; -import static org.junit.jupiter.api.AssertionUtils.format; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.Supplier; @@ -40,12 +38,16 @@ static void assertSame(Object expected, Object actual, String message) { static void assertSame(Object expected, Object actual, Supplier messageSupplier) { if (expected != actual) { - failNotSame(expected, actual, nullSafeGet(messageSupplier)); + failNotSame(expected, actual, messageSupplier); } } - private static void failNotSame(Object expected, Object actual, String message) { - fail(format(expected, actual, message), expected, actual); + private static void failNotSame(Object expected, Object actual, Object messageOrSupplier) { + assertionFailure() // + .message(messageOrSupplier) // + .expected(expected) // + .actual(actual) // + .buildAndThrow(); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java index 9be0d9a2f1d1..08d64d42abc0 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java @@ -10,16 +10,13 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; -import static org.junit.jupiter.api.AssertionUtils.format; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.getCanonicalName; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; import java.util.function.Supplier; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.util.UnrecoverableExceptions; -import org.opentest4j.AssertionFailedError; /** * {@code AssertThrows} is a collection of utility methods that support asserting @@ -60,15 +57,18 @@ private static T assertThrows(Class expectedType, Execu } else { UnrecoverableExceptions.rethrowIfUnrecoverable(actualException); - String message = buildPrefix(nullSafeGet(messageOrSupplier)) - + format(expectedType, actualException.getClass(), "Unexpected exception type thrown"); - throw new AssertionFailedError(message, actualException); + throw assertionFailure() // + .message(messageOrSupplier) // + .expected(expectedType) // + .actual(actualException.getClass()) // + .reason("Unexpected exception type thrown") // + .build(); } } - - String message = buildPrefix(nullSafeGet(messageOrSupplier)) - + String.format("Expected %s to be thrown, but nothing was thrown.", getCanonicalName(expectedType)); - throw new AssertionFailedError(message); + throw assertionFailure() // + .message(messageOrSupplier) // + .reason(String.format("Expected %s to be thrown, but nothing was thrown.", + getCanonicalName(expectedType))).build(); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrowsExactly.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrowsExactly.java index f40a05f273f0..03f36565cce4 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrowsExactly.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrowsExactly.java @@ -10,16 +10,13 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; -import static org.junit.jupiter.api.AssertionUtils.format; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.getCanonicalName; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; import java.util.function.Supplier; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.util.UnrecoverableExceptions; -import org.opentest4j.AssertionFailedError; /** * {@code AssertThrowsExactly} is a collection of utility methods that support asserting @@ -60,15 +57,19 @@ private static T assertThrowsExactly(Class expectedType } else { UnrecoverableExceptions.rethrowIfUnrecoverable(actualException); - String message = buildPrefix(nullSafeGet(messageOrSupplier)) - + format(expectedType, actualException.getClass(), "Unexpected exception type thrown"); - throw new AssertionFailedError(message, actualException); + throw assertionFailure() // + .message(messageOrSupplier) // + .expected(expectedType) // + .actual(actualException.getClass()) // + .reason("Unexpected exception type thrown") // + .build(); } } - String message = buildPrefix(nullSafeGet(messageOrSupplier)) - + String.format("Expected %s to be thrown, but nothing was thrown.", getCanonicalName(expectedType)); - throw new AssertionFailedError(message); + throw assertionFailure() // + .message(messageOrSupplier) // + .reason(String.format("Expected %s to be thrown, but nothing was thrown.", + getCanonicalName(expectedType))).build(); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeout.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeout.java index d5634c578d31..81268f7eafec 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeout.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeout.java @@ -10,9 +10,7 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; -import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.time.Duration; import java.util.concurrent.ExecutionException; @@ -30,7 +28,6 @@ import org.junit.jupiter.api.function.ThrowingSupplier; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ExceptionUtils; -import org.opentest4j.AssertionFailedError; /** * {@code AssertTimeout} is a collection of utility methods that support asserting @@ -87,8 +84,11 @@ private static T assertTimeout(Duration timeout, ThrowingSupplier supplie long timeElapsed = System.currentTimeMillis() - start; if (timeElapsed > timeoutInMillis) { - fail(buildPrefix(nullSafeGet(messageOrSupplier)) + "execution exceeded timeout of " + timeoutInMillis - + " ms by " + (timeElapsed - timeoutInMillis) + " ms"); + assertionFailure() // + .message(messageOrSupplier) // + .reason("execution exceeded timeout of " + timeoutInMillis + " ms by " + + (timeElapsed - timeoutInMillis) + " ms") // + .buildAndThrow(); } return result; } @@ -147,19 +147,18 @@ private static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplie return future.get(timeoutInMillis, TimeUnit.MILLISECONDS); } catch (TimeoutException ex) { - String message = buildPrefix(nullSafeGet(messageOrSupplier)) + "execution timed out after " - + timeoutInMillis + " ms"; + AssertionFailureBuilder failure = assertionFailure() // + .message(messageOrSupplier) // + .reason("execution timed out after " + timeoutInMillis + " ms"); Thread thread = threadReference.get(); if (thread != null) { ExecutionTimeoutException exception = new ExecutionTimeoutException( "Execution timed out in thread " + thread.getName()); exception.setStackTrace(thread.getStackTrace()); - throw new AssertionFailedError(message, exception); - } - else { - throw new AssertionFailedError(message); + failure.cause(exception); } + throw failure.build(); } catch (ExecutionException ex) { throw ExceptionUtils.throwAsUncheckedException(ex.getCause()); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTrue.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTrue.java index 92e4451db0f2..3d250a46f68e 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTrue.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTrue.java @@ -10,9 +10,7 @@ package org.junit.jupiter.api; -import static org.junit.jupiter.api.AssertionUtils.buildPrefix; -import static org.junit.jupiter.api.AssertionUtils.fail; -import static org.junit.jupiter.api.AssertionUtils.nullSafeGet; +import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.BooleanSupplier; import java.util.function.Supplier; @@ -25,8 +23,6 @@ */ class AssertTrue { - private static final String EXPECTED_TRUE = "expected: but was: "; - private AssertTrue() { /* no-op */ } @@ -37,13 +33,13 @@ static void assertTrue(boolean condition) { static void assertTrue(boolean condition, String message) { if (!condition) { - fail(buildPrefix(message) + EXPECTED_TRUE, true, false); + failNotTrue(message); } } static void assertTrue(boolean condition, Supplier messageSupplier) { if (!condition) { - fail(buildPrefix(nullSafeGet(messageSupplier)) + EXPECTED_TRUE, true, false); + failNotTrue(messageSupplier); } } @@ -59,4 +55,12 @@ static void assertTrue(BooleanSupplier booleanSupplier, Supplier message assertTrue(booleanSupplier.getAsBoolean(), messageSupplier); } + private static void failNotTrue(Object messageOrSupplier) { + assertionFailure() // + .message(messageOrSupplier) // + .expected(true) // + .actual(false) // + .buildAndThrow(); + } + } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java new file mode 100644 index 000000000000..ebfc9dd2ba57 --- /dev/null +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java @@ -0,0 +1,153 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.jupiter.api; + +import static org.junit.jupiter.api.AssertionUtils.getCanonicalName; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Supplier; + +import org.junit.platform.commons.util.StringUtils; +import org.opentest4j.AssertionFailedError; + +public class AssertionFailureBuilder { + + private Object message; + private Throwable cause; + private final List suppressed = new ArrayList<>(); + private boolean mismatch; + private Object expected; + private Object actual; + private String reason; + private boolean includeValuesInMessage = true; + + public static AssertionFailureBuilder assertionFailure() { + return new AssertionFailureBuilder(); + } + + private AssertionFailureBuilder() { + } + + public AssertionFailureBuilder message(Object message) { + this.message = message; + return this; + } + + public AssertionFailureBuilder reason(String reason) { + this.reason = reason; + return this; + } + + public AssertionFailureBuilder cause(Throwable cause) { + this.cause = cause; + return this; + } + + public AssertionFailureBuilder suppressed(Throwable suppressed) { + this.suppressed.add(suppressed); + return this; + } + + public AssertionFailureBuilder suppressed(Throwable... suppressed) { + this.suppressed.addAll(Arrays.asList(suppressed)); + return this; + } + + public AssertionFailureBuilder expected(Object expected) { + this.mismatch = true; + this.expected = expected; + return this; + } + + public AssertionFailureBuilder actual(Object actual) { + this.mismatch = true; + this.actual = actual; + return this; + } + + public AssertionFailureBuilder includeValuesInMessage(boolean includeValuesInMessage) { + this.includeValuesInMessage = includeValuesInMessage; + return this; + } + + public void buildAndThrow() throws AssertionFailedError { + throw build(); + } + + public AssertionFailedError build() { + String reason = nullSafeGet(this.reason); + if (mismatch && includeValuesInMessage) { + reason = (reason == null ? "" : reason + ", ") + formatValues(expected, actual); + } + String message = nullSafeGet(this.message); + if (reason != null) { + message = buildPrefix(message) + reason; + } + AssertionFailedError assertionFailedError = mismatch // + ? new AssertionFailedError(message, expected, actual, cause) // + : new AssertionFailedError(message, cause); + suppressed.forEach(assertionFailedError::addSuppressed); + return assertionFailedError; + } + + private static String nullSafeGet(Object messageOrSupplier) { + if (messageOrSupplier == null) { + return null; + } + if (messageOrSupplier instanceof Supplier) { + Object message = ((Supplier) messageOrSupplier).get(); + return message == null ? null : message.toString(); + } + return String.valueOf(messageOrSupplier); + } + + private static String buildPrefix(String message) { + return (StringUtils.isNotBlank(message) ? message + " ==> " : ""); + } + + private static String formatValues(Object expected, Object actual) { + String expectedString = toString(expected); + String actualString = toString(actual); + if (expectedString.equals(actualString)) { + return String.format("expected: %s but was: %s", formatClassAndValue(expected, expectedString), + formatClassAndValue(actual, actualString)); + } + return String.format("expected: <%s> but was: <%s>", expectedString, actualString); + } + + private static String formatClassAndValue(Object value, String valueString) { + // If the value is null, return instead of null. + if (value == null) { + return ""; + } + String classAndHash = getClassName(value) + toHash(value); + // if it's a class, there's no need to repeat the class name contained in the valueString. + return (value instanceof Class ? "<" + classAndHash + ">" : classAndHash + "<" + valueString + ">"); + } + + private static String toString(Object obj) { + if (obj instanceof Class) { + return getCanonicalName((Class) obj); + } + return StringUtils.nullSafeToString(obj); + } + + private static String toHash(Object obj) { + return (obj == null ? "" : "@" + Integer.toHexString(System.identityHashCode(obj))); + } + + private static String getClassName(Object obj) { + return (obj == null ? "null" + : obj instanceof Class ? getCanonicalName((Class) obj) : obj.getClass().getName()); + } +} diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java index 524f8142901b..c591c217dadb 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java @@ -15,7 +15,6 @@ import java.util.Deque; import java.util.function.Supplier; -import org.junit.platform.commons.util.StringUtils; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.opentest4j.AssertionFailedError; @@ -51,52 +50,10 @@ static void fail(Supplier messageSupplier) { throw new AssertionFailedError(nullSafeGet(messageSupplier)); } - static void fail(String message, Object expected, Object actual) { - throw new AssertionFailedError(message, expected, actual); - } - - /** - * Typically used for {@code assertEquals()}. - */ - static void failNotEqual(Object expected, Object actual, String message) { - fail(format(expected, actual, message), expected, actual); - } - - /** - * Typically used for {@code assertEquals()}. - */ - static void failNotEqual(Object expected, Object actual, Supplier messageSupplier) { - fail(format(expected, actual, nullSafeGet(messageSupplier)), expected, actual); - } - static String nullSafeGet(Supplier messageSupplier) { return (messageSupplier != null ? messageSupplier.get() : null); } - /** - * Alternative to {@link #nullSafeGet(Supplier)} that is used to avoid - * wrapping a String in a lambda expression. - * - * @param messageOrSupplier an object that is either a {@code String} or - * {@code Supplier} - */ - static String nullSafeGet(Object messageOrSupplier) { - if (messageOrSupplier instanceof String) { - return (String) messageOrSupplier; - } - if (messageOrSupplier instanceof Supplier) { - Object message = ((Supplier) messageOrSupplier).get(); - if (message != null) { - return message.toString(); - } - } - return null; - } - - static String buildPrefix(String message) { - return (StringUtils.isNotBlank(message) ? message + " ==> " : ""); - } - static String getCanonicalName(Class clazz) { try { String canonicalName = clazz.getCanonicalName(); @@ -108,46 +65,6 @@ static String getCanonicalName(Class clazz) { } } - static String format(Object expected, Object actual, String message) { - return buildPrefix(message) + formatValues(expected, actual); - } - - static String formatValues(Object expected, Object actual) { - String expectedString = toString(expected); - String actualString = toString(actual); - if (expectedString.equals(actualString)) { - return String.format("expected: %s but was: %s", formatClassAndValue(expected, expectedString), - formatClassAndValue(actual, actualString)); - } - return String.format("expected: <%s> but was: <%s>", expectedString, actualString); - } - - private static String formatClassAndValue(Object value, String valueString) { - // If the value is null, return instead of null. - if (value == null) { - return ""; - } - String classAndHash = getClassName(value) + toHash(value); - // if it's a class, there's no need to repeat the class name contained in the valueString. - return (value instanceof Class ? "<" + classAndHash + ">" : classAndHash + "<" + valueString + ">"); - } - - private static String toString(Object obj) { - if (obj instanceof Class) { - return getCanonicalName((Class) obj); - } - return StringUtils.nullSafeToString(obj); - } - - private static String toHash(Object obj) { - return (obj == null ? "" : "@" + Integer.toHexString(System.identityHashCode(obj))); - } - - private static String getClassName(Object obj) { - return (obj == null ? "null" - : obj instanceof Class ? getCanonicalName((Class) obj) : obj.getClass().getName()); - } - static String formatIndexes(Deque indexes) { if (indexes == null || indexes.isEmpty()) { return ""; diff --git a/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/AssertInstanceOfAssertionsTests.java b/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/AssertInstanceOfAssertionsTests.java index bdf0b8476f71..12ba2fa92f9f 100644 --- a/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/AssertInstanceOfAssertionsTests.java +++ b/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/AssertInstanceOfAssertionsTests.java @@ -93,7 +93,7 @@ private void assertInstanceOfSucceeds(Class expectedType, Object actualVa private void assertInstanceOfFails(Class expectedType, Object actualValue, String unexpectedSort) { String valueType = actualValue == null ? "null" : actualValue.getClass().getCanonicalName(); - String expectedMessage = String.format("Unexpected %s ==> expected: <%s> but was: <%s>", unexpectedSort, + String expectedMessage = String.format("Unexpected %s, expected: <%s> but was: <%s>", unexpectedSort, expectedType.getCanonicalName(), valueType); assertThrowsWithMessage(expectedMessage, () -> assertInstanceOf(expectedType, actualValue)); diff --git a/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/AssertThrowsAssertionsTests.java b/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/AssertThrowsAssertionsTests.java index 5239f0f1c944..4d3b10fe381a 100644 --- a/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/AssertThrowsAssertionsTests.java +++ b/junit-jupiter-engine/src/test/java/org/junit/jupiter/api/AssertThrowsAssertionsTests.java @@ -152,7 +152,7 @@ void assertThrowsWithExecutableThatThrowsAnUnexpectedException() { expectAssertionFailedError(); } catch (AssertionFailedError ex) { - assertMessageStartsWith(ex, "Unexpected exception type thrown ==> "); + assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); } @@ -168,9 +168,9 @@ void assertThrowsWithExecutableThatThrowsAnUnexpectedExceptionWithMessageString( } catch (AssertionFailedError ex) { // Should look something like this: - // Custom message ==> Unexpected exception type thrown ==> expected: but was: + // Custom message ==> Unexpected exception type thrown, expected: but was: assertMessageStartsWith(ex, "Custom message ==> "); - assertMessageContains(ex, "Unexpected exception type thrown ==> "); + assertMessageContains(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); } @@ -186,9 +186,9 @@ void assertThrowsWithExecutableThatThrowsAnUnexpectedExceptionWithMessageSupplie } catch (AssertionFailedError ex) { // Should look something like this: - // Custom message ==> Unexpected exception type thrown ==> expected: but was: + // Custom message ==> Unexpected exception type thrown, expected: but was: assertMessageStartsWith(ex, "Custom message ==> "); - assertMessageContains(ex, "Unexpected exception type thrown ==> "); + assertMessageContains(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); } @@ -205,7 +205,7 @@ void assertThrowsWithExecutableThatThrowsInstanceOfAnonymousInnerClassAsUnexpect expectAssertionFailedError(); } catch (AssertionFailedError ex) { - assertMessageStartsWith(ex, "Unexpected exception type thrown ==> "); + assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); // As of the time of this writing, the class name of the above anonymous inner // class is org.junit.jupiter.api.AssertionsAssertThrowsTests$2; however, hard @@ -224,7 +224,7 @@ void assertThrowsWithExecutableThatThrowsInstanceOfStaticNestedClassAsUnexpected expectAssertionFailedError(); } catch (AssertionFailedError ex) { - assertMessageStartsWith(ex, "Unexpected exception type thrown ==> "); + assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); // The following verifies that the canonical name is used (i.e., "." instead of "$"). assertMessageContains(ex, "but was: <" + LocalException.class.getName().replace("$", ".") + ">"); @@ -249,11 +249,11 @@ void assertThrowsWithExecutableThatThrowsSameExceptionTypeFromDifferentClassLoad catch (AssertionFailedError ex) { // Example Output: // - // Unexpected exception type thrown ==> + // Unexpected exception type thrown, // expected: // but was: - assertMessageStartsWith(ex, "Unexpected exception type thrown ==> "); + assertMessageStartsWith(ex, "Unexpected exception type thrown, "); // The presence of the "@" sign is sufficient to indicate that the hash was // generated to disambiguate between the two identical class names. assertMessageContains(ex, "expected: "); + assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); } @@ -69,7 +69,7 @@ void assertThrowsExactlyWithTheExpectedParentException() { expectAssertionFailedError(); } catch (AssertionFailedError ex) { - assertMessageStartsWith(ex, "Unexpected exception type thrown ==> "); + assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); } @@ -191,7 +191,7 @@ void assertThrowsWithExecutableThatThrowsAnUnexpectedException() { expectAssertionFailedError(); } catch (AssertionFailedError ex) { - assertMessageStartsWith(ex, "Unexpected exception type thrown ==> "); + assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); } @@ -207,9 +207,9 @@ void assertThrowsWithExecutableThatThrowsAnUnexpectedExceptionWithMessageString( } catch (AssertionFailedError ex) { // Should look something like this: - // Custom message ==> Unexpected exception type thrown ==> expected: but was: + // Custom message ==> Unexpected exception type thrown, expected: but was: assertMessageStartsWith(ex, "Custom message ==> "); - assertMessageContains(ex, "Unexpected exception type thrown ==> "); + assertMessageContains(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); } @@ -225,9 +225,9 @@ void assertThrowsWithExecutableThatThrowsAnUnexpectedExceptionWithMessageSupplie } catch (AssertionFailedError ex) { // Should look something like this: - // Custom message ==> Unexpected exception type thrown ==> expected: but was: + // Custom message ==> Unexpected exception type thrown, expected: but was: assertMessageStartsWith(ex, "Custom message ==> "); - assertMessageContains(ex, "Unexpected exception type thrown ==> "); + assertMessageContains(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); assertMessageContains(ex, "but was: "); } @@ -244,7 +244,7 @@ void assertThrowsWithExecutableThatThrowsInstanceOfAnonymousInnerClassAsUnexpect expectAssertionFailedError(); } catch (AssertionFailedError ex) { - assertMessageStartsWith(ex, "Unexpected exception type thrown ==> "); + assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); // As of the time of this writing, the class name of the above anonymous inner // class is org.junit.jupiter.api.AssertThrowsExactlyAssertionsTests$2; however, hard @@ -263,7 +263,7 @@ void assertThrowsWithExecutableThatThrowsInstanceOfStaticNestedClassAsUnexpected expectAssertionFailedError(); } catch (AssertionFailedError ex) { - assertMessageStartsWith(ex, "Unexpected exception type thrown ==> "); + assertMessageStartsWith(ex, "Unexpected exception type thrown, "); assertMessageContains(ex, "expected: "); // The following verifies that the canonical name is used (i.e., "." instead of "$"). assertMessageContains(ex, "but was: <" + LocalException.class.getName().replace("$", ".") + ">"); @@ -288,11 +288,11 @@ void assertThrowsWithExecutableThatThrowsSameExceptionTypeFromDifferentClassLoad catch (AssertionFailedError ex) { // Example Output: // - // Unexpected exception type thrown ==> + // Unexpected exception type thrown, // expected: // but was: - assertMessageStartsWith(ex, "Unexpected exception type thrown ==> "); + assertMessageStartsWith(ex, "Unexpected exception type thrown, "); // The presence of the "@" sign is sufficient to indicate that the hash was // generated to disambiguate between the two identical class names. assertMessageContains(ex, "expected: