Skip to content

Commit bc68cc8

Browse files
committed
Prune org.junit.start from exceptions
When using `JUnit.start` the `pruneStackTrace` algorithm immediately sees the `TestClass.main` frame and assumes that this is the test method because the test class name matches. ``` org.opentest4j.AssertionFailedError: expected: <11> but was: <12> at org.junit.jupiter.api@6.1.0-SNAPSHOT/org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:158) at org.junit.jupiter.api@6.1.0-SNAPSHOT/org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:139) at org.junit.jupiter.api@6.1.0-SNAPSHOT/org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:201) at org.junit.jupiter.api@6.1.0-SNAPSHOT/org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:152) at org.junit.jupiter.api@6.1.0-SNAPSHOT/org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:147) at org.junit.jupiter.api@6.1.0-SNAPSHOT/org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:558) at com.examp.project/com.example.project.HelloTest.stringLength(HelloTest.java:14) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ... at org.junit.platform.launcher@6.1.0-SNAPSHOT/org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:81) at org.junit.start@6.1.0-SNAPSHOT/org.junit.start.JUnit.run(JUnit.java:63) at org.junit.start@6.1.0-SNAPSHOT/org.junit.start.JUnit.run(JUnit.java:37) at com.examp.project/com.example.project.HelloTest.main(HelloTest.java:9) ``` By checking if `org.junit.start` is involved further down the stack we exclude this scenario.
1 parent 49ba3f2 commit bc68cc8

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

junit-platform-commons/src/main/java/org/junit/platform/commons/util/ExceptionUtils.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public static void pruneStackTrace(Throwable throwable, List<String> classNames)
133133
StackTraceElement element = stackTrace.get(i);
134134
String className = element.getClassName();
135135

136-
if (classNames.contains(className)) {
136+
if (classNames.contains(className) && !includesJunitStart(stackTrace, i + 1)) {
137137
// We found the test
138138
// everything before that is not informative.
139139
prunedStackTrace.clear();
@@ -156,6 +156,13 @@ else if (STACK_TRACE_ELEMENT_FILTER.test(className)) {
156156
throwable.setStackTrace(prunedStackTrace.toArray(new StackTraceElement[0]));
157157
}
158158

159+
private static boolean includesJunitStart(List<StackTraceElement> stackTrace, int fromIndex) {
160+
return stackTrace.stream()
161+
.skip(fromIndex)
162+
.map(StackTraceElement::getClassName)
163+
.anyMatch(className -> className.startsWith(JUNIT_START_PACKAGE_PREFIX));
164+
}
165+
159166
/**
160167
* Find all causes and suppressed exceptions in the stack trace of the
161168
* supplied {@link Throwable}.

platform-tests/src/test/java/org/junit/platform/commons/util/ExceptionUtilsTests.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import static org.junit.platform.commons.util.ExceptionUtils.throwAsUncheckedException;
2020

2121
import java.io.IOException;
22+
import java.util.ArrayList;
23+
import java.util.Arrays;
2224
import java.util.List;
2325

2426
import org.junit.jupiter.api.Test;
@@ -104,6 +106,21 @@ void pruneStackTraceOfEverythingPriorToFirstLauncherCall() {
104106
.noneMatch(element -> element.toString().contains("org.example.Class.method(file:123)"));
105107
}
106108

109+
@Test
110+
void pruneStackTraceOfJUnitStart() {
111+
JUnitException exception = new JUnitException("expected");
112+
List<StackTraceElement> stackTrace = new ArrayList<>(Arrays.asList(exception.getStackTrace()));
113+
String testClassName = ExceptionUtilsTests.class.getCanonicalName();
114+
stackTrace.add(new StackTraceElement("org.junit.start.JUnit", "run", "JUnit.class", 456));
115+
stackTrace.add(new StackTraceElement(testClassName, "main", "ExceptionUtilsTest.class", 123));
116+
exception.setStackTrace(stackTrace.toArray(new StackTraceElement[0]));
117+
118+
pruneStackTrace(exception, List.of(testClassName));
119+
120+
assertThat(exception.getStackTrace()) //
121+
.noneMatch(element -> element.toString().contains(testClassName + ".main(file:123)"));
122+
}
123+
107124
@Test
108125
void findSuppressedExceptionsAndCausesOfThrowable() {
109126
Throwable t1 = new Throwable("#1");

0 commit comments

Comments
 (0)