Add undeclared test case failures to test.xml
This matches the behavior of the maven surefire plugin.
Fixes #19949
Closes #19966.
PiperOrigin-RevId: 578255510
Change-Id: I2512c387ee63adf054de8af3e19e9ddedc4e368d
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteModel.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteModel.java
index 3a90867..a9ca4cf 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteModel.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestSuiteModel.java
@@ -182,6 +182,23 @@
} else {
test.testFailure(throwable, now());
}
+ } else {
+ // this is a test case dynamically added by the suite runner (such as mockito)
+ TestSuiteNode testSuite =
+ (TestSuiteNode)
+ rootNode.getChildren().stream()
+ .filter(node -> node instanceof TestSuiteNode)
+ .filter(
+ node ->
+ node.getDescription().getTestClass().equals(description.getTestClass()))
+ .findAny()
+ .orElseThrow(() -> new IllegalStateException("expected to find test suite node"));
+ TestCaseNode testCase = new TestCaseNode(description, testSuite);
+ testsMap.put(description, testCase);
+ testCaseMap.put(description, testCase);
+ testSuite.addTestCase(testCase);
+ // since this is the first time we're learning of this, the timing data will be incorrect :(
+ testCase.testFailure(throwable, now());
}
}
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4_testbridge_integration_tests.sh b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4_testbridge_integration_tests.sh
index ac006c8..2494005 100755
--- a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4_testbridge_integration_tests.sh
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/junit4_testbridge_integration_tests.sh
@@ -108,4 +108,16 @@
expect_log 'Failures: 2'
}
+# Test that we fail on suite failures even if individual test cases pass
+function test_JunitUndeclaredTestCaseFailures() {
+ cd "${TEST_TMPDIR}" || fail "Unexpected failure"
+
+ "${TESTBED}" \
+ --jvm_flag="-D${SUITE_PARAMETER}=com.google.testing.junit.runner.testbed.Junit4UndeclaredTestCaseFailures" \
+ &> "${TEST_log}" && fail "Expected failure"
+ expect_log 'unnecessary Mockito stubbings'
+ grep -q "tests='2' failures='1'" ${XML_OUTPUT_FILE} || \
+ fail "Expected 1 failure in xml output: `cat ${XML_OUTPUT_FILE}`"
+}
+
run_suite "junit4_testbridge_integration_test"
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/BUILD b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/BUILD
index 33de6c4..97a9e74 100644
--- a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/BUILD
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/BUILD
@@ -14,6 +14,7 @@
deps = [
"//third_party:guava",
"//third_party:junit4",
+ "//third_party:mockito",
"//third_party:truth",
],
)
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/Junit4UndeclaredTestCaseFailures.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/Junit4UndeclaredTestCaseFailures.java
new file mode 100644
index 0000000..ef1d591
--- /dev/null
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/testbed/Junit4UndeclaredTestCaseFailures.java
@@ -0,0 +1,36 @@
+// Copyright 2023 The Bazel Authors. All Rights Reserved.
+//
+// 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.
+
+package com.google.testing.junit.runner.testbed;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+/** A JUnit4-style test meant to be invoked by junit4_testbridge_tests.sh. */
+@RunWith(MockitoJUnitRunner.Strict.class)
+public class Junit4UndeclaredTestCaseFailures {
+
+ @SuppressWarnings("unchecked")
+ private final List<String> mockList = mock(List.class);
+
+ @Test
+ public void passesButHasUnnecessaryStubs() {
+ when(mockList.add("")).thenReturn(true); // this won't get called
+ }
+}