Skip to content

Commit f5fffa1

Browse files
committed
Prefer public methods for Vintage MethodSources
Since JUnit requires test methods to be public, prefer such methods over other methods with the same name when creating the `MethodSource` for a JUnit 4 `Description` instance. Resolves #1904.
1 parent 00bd3fe commit f5fffa1

File tree

6 files changed

+88
-20
lines changed

6 files changed

+88
-20
lines changed

documentation/src/docs/asciidoc/release-notes/release-notes-5.5.0-RC1.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,5 @@ on GitHub.
9999

100100
* `junit:junit` is now a compile-scoped dependency of `junit-vintage-engine` to allow for
101101
easier dependency management in Maven POMs.
102+
* Methods that are `public` are now preferred over other methods with the same name in the
103+
same test class when creating `MethodSources` for JUnit 4 `Descriptions`.

junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/VintageTestDescriptor.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
import static java.util.Arrays.stream;
1414
import static java.util.function.Predicate.isEqual;
15+
import static java.util.stream.Collectors.toList;
1516
import static org.apiguardian.api.API.Status.INTERNAL;
16-
import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement;
1717
import static org.junit.platform.commons.util.FunctionUtils.where;
1818
import static org.junit.platform.commons.util.ReflectionUtils.findMethods;
1919
import static org.junit.platform.commons.util.StringUtils.isNotBlank;
@@ -28,6 +28,7 @@
2828

2929
import org.apiguardian.api.API;
3030
import org.junit.experimental.categories.Category;
31+
import org.junit.platform.commons.support.ModifierSupport;
3132
import org.junit.platform.commons.util.ReflectionUtils;
3233
import org.junit.platform.engine.TestDescriptor;
3334
import org.junit.platform.engine.TestSource;
@@ -148,25 +149,33 @@ private static TestSource toTestSource(Description description) {
148149
if (testClass != null) {
149150
String methodName = description.getMethodName();
150151
if (methodName != null) {
151-
MethodSource methodSource = toMethodSource(testClass, methodName);
152-
if (methodSource != null) {
153-
return methodSource;
152+
Method method = findMethod(testClass, methodName);
153+
if (method != null) {
154+
return MethodSource.from(testClass, method);
154155
}
155156
}
156157
return ClassSource.from(testClass);
157158
}
158159
return null;
159160
}
160161

161-
private static MethodSource toMethodSource(Class<?> testClass, String methodName) {
162+
private static Method findMethod(Class<?> testClass, String methodName) {
162163
if (methodName.contains("[") && methodName.endsWith("]")) {
163164
// special case for parameterized tests
164-
return toMethodSource(testClass, methodName.substring(0, methodName.indexOf("[")));
165+
return findMethod(testClass, methodName.substring(0, methodName.indexOf("[")));
165166
}
166-
else {
167-
List<Method> methods = findMethods(testClass, where(Method::getName, isEqual(methodName)));
168-
return (methods.size() == 1) ? MethodSource.from(testClass, getOnlyElement(methods)) : null;
167+
List<Method> methods = findMethods(testClass, where(Method::getName, isEqual(methodName)));
168+
if (methods.isEmpty()) {
169+
return null;
170+
}
171+
if (methods.size() == 1) {
172+
return methods.get(0);
169173
}
174+
methods = methods.stream().filter(ModifierSupport::isPublic).collect(toList());
175+
if (methods.size() == 1) {
176+
return methods.get(0);
177+
}
178+
return null;
170179
}
171180

172181
}

junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineDiscoveryTests.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@
6060
import org.junit.vintage.engine.samples.junit4.IgnoredJUnit4TestCase;
6161
import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithPlainJUnit4TestCaseWithSingleTestWhichIsIgnored;
6262
import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithTwoTestCases;
63+
import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithDistinguishableOverloadedMethod;
64+
import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithIndistinguishableOverloadedMethod;
6365
import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithNotFilterableRunner;
64-
import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithOverloadedMethod;
6566
import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithRunnerWithCustomUniqueIds;
6667
import org.junit.vintage.engine.samples.junit4.ParameterizedTestCase;
6768
import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithFiveTestMethods;
@@ -196,8 +197,8 @@ void resolvesJUnit4SuiteWithPlainJUnit4TestCaseWithSingleTestWhichIsIgnored() th
196197
}
197198

198199
@Test
199-
void resolvesJUnit4TestCaseWithOverloadedMethod() {
200-
Class<?> testClass = JUnit4TestCaseWithOverloadedMethod.class;
200+
void resolvesJUnit4TestCaseWithIndistinguishableOverloadedMethod() {
201+
Class<?> testClass = JUnit4TestCaseWithIndistinguishableOverloadedMethod.class;
201202
LauncherDiscoveryRequest discoveryRequest = discoveryRequestForClass(testClass);
202203

203204
TestDescriptor engineDescriptor = discoverTests(discoveryRequest);
@@ -221,6 +222,24 @@ void resolvesJUnit4TestCaseWithOverloadedMethod() {
221222
assertClassSource(testClass, testMethodDescriptor);
222223
}
223224

225+
@Test
226+
void resolvesJUnit4TestCaseWithDistinguishableOverloadedMethod() throws Exception {
227+
Class<?> testClass = JUnit4TestCaseWithDistinguishableOverloadedMethod.class;
228+
LauncherDiscoveryRequest discoveryRequest = discoveryRequestForClass(testClass);
229+
230+
TestDescriptor engineDescriptor = discoverTests(discoveryRequest);
231+
232+
TestDescriptor runnerDescriptor = getOnlyElement(engineDescriptor.getChildren());
233+
assertRunnerTestDescriptor(runnerDescriptor, testClass);
234+
235+
List<TestDescriptor> testMethodDescriptors = new ArrayList<>(runnerDescriptor.getChildren());
236+
237+
TestDescriptor testMethodDescriptor = getOnlyElement(testMethodDescriptors);
238+
assertEquals("test", testMethodDescriptor.getDisplayName());
239+
assertEquals(VintageUniqueIdBuilder.uniqueIdForMethod(testClass, "test"), testMethodDescriptor.getUniqueId());
240+
assertMethodSource(testClass.getMethod("test"), testMethodDescriptor);
241+
}
242+
224243
@Test
225244
void doesNotResolvePlainOldJavaClassesWithoutAnyTest() {
226245
assertYieldsNoDescriptors(PlainOldJavaClassWithoutAnyTestsTestCase.class);
@@ -283,7 +302,7 @@ void resolvesApplyingClassNameFilters() throws Exception {
283302
assertThat(engineDescriptor.getChildren())
284303
.extracting(TestDescriptor::getDisplayName)
285304
.contains(PlainJUnit4TestCaseWithSingleTestWhichFails.class.getSimpleName())
286-
.doesNotContain(JUnit4TestCaseWithOverloadedMethod.class.getSimpleName())
305+
.doesNotContain(JUnit4TestCaseWithIndistinguishableOverloadedMethod.class.getSimpleName())
287306
.doesNotContain(PlainJUnit3TestCaseWithSingleTestWhichFails.class.getSimpleName());
288307
// @formatter:on
289308
}

junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineExecutionTests.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithErrorInBeforeClass;
7070
import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithExceptionThrowingRunner;
7171
import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithFailingDescriptionThatIsNotReportedAsFinished;
72-
import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithOverloadedMethod;
72+
import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithIndistinguishableOverloadedMethod;
7373
import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithRunnerWithCustomUniqueIds;
7474
import org.junit.vintage.engine.samples.junit4.MalformedJUnit4TestCase;
7575
import org.junit.vintage.engine.samples.junit4.ParameterizedTestCase;
@@ -282,15 +282,19 @@ void executesJUnit4TestCaseWithErrorInAfterClass() {
282282

283283
@Test
284284
void executesJUnit4TestCaseWithOverloadedMethod() {
285-
Class<?> testClass = JUnit4TestCaseWithOverloadedMethod.class;
285+
Class<?> testClass = JUnit4TestCaseWithIndistinguishableOverloadedMethod.class;
286286

287287
execute(testClass).assertEventsMatchExactly( //
288288
event(engine(), started()), //
289289
event(container(testClass), started()), //
290-
event(test("theory(" + JUnit4TestCaseWithOverloadedMethod.class.getName() + ")[0]"), started()), //
291-
event(test("theory(" + JUnit4TestCaseWithOverloadedMethod.class.getName() + ")[0]"), finishedWithFailure()), //
292-
event(test("theory(" + JUnit4TestCaseWithOverloadedMethod.class.getName() + ")[1]"), started()), //
293-
event(test("theory(" + JUnit4TestCaseWithOverloadedMethod.class.getName() + ")[1]"), finishedWithFailure()), //
290+
event(test("theory(" + JUnit4TestCaseWithIndistinguishableOverloadedMethod.class.getName() + ")[0]"),
291+
started()), //
292+
event(test("theory(" + JUnit4TestCaseWithIndistinguishableOverloadedMethod.class.getName() + ")[0]"),
293+
finishedWithFailure()), //
294+
event(test("theory(" + JUnit4TestCaseWithIndistinguishableOverloadedMethod.class.getName() + ")[1]"),
295+
started()), //
296+
event(test("theory(" + JUnit4TestCaseWithIndistinguishableOverloadedMethod.class.getName() + ")[1]"),
297+
finishedWithFailure()), //
294298
event(container(testClass), finishedSuccessfully()), //
295299
event(engine(), finishedSuccessfully()));
296300
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2015-2019 the original author or authors.
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License v2.0 which
6+
* accompanies this distribution and is available at
7+
*
8+
* https://www.eclipse.org/legal/epl-v20.html
9+
*/
10+
11+
package org.junit.vintage.engine.samples.junit4;
12+
13+
import static org.junit.Assert.fail;
14+
15+
import org.junit.Test;
16+
import org.junit.experimental.theories.Theories;
17+
import org.junit.runner.RunWith;
18+
19+
/**
20+
* @since 5.5
21+
*/
22+
@RunWith(Theories.class)
23+
public class JUnit4TestCaseWithDistinguishableOverloadedMethod {
24+
25+
@Test
26+
public void test() {
27+
test("foo");
28+
}
29+
30+
private void test(String message) {
31+
fail(message);
32+
}
33+
34+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
* @since 4.12
2222
*/
2323
@RunWith(Theories.class)
24-
public class JUnit4TestCaseWithOverloadedMethod {
24+
public class JUnit4TestCaseWithIndistinguishableOverloadedMethod {
2525

2626
@DataPoint
2727
public static int MAGIC_NUMBER = 42;

0 commit comments

Comments
 (0)