Product: SonarQube Community 26.4.0.121862
sonar-java version: sonar-java 8.28.0.43176
sonar-java SE version: sonar-java-symbolic-execution 8.16.3.1589
Java source level: 21 (javac 21, source/target 17)
Rule
java:S1144 — Unused “private” methods should be removed
Description
SonarJava incorrectly reports a private static method as unused when it is used implicitly via JUnit 5 @MethodSource without an explicit value. In this case, JUnit resolves the method by matching the test method name and calls it reflectively at runtime, so the method is actually used. S1144 should treat this implicit resolution the same as the explicit @MethodSource("methodName") form.
Reproducer
// AFTER — S1144 false positive
package demo.after;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.stream.Stream;
public class MethodSourceTest {
private enum Color { RED, GREEN, BLUE }
@ParameterizedTest
@MethodSource // implicit: resolves to a factory named "testColorProcessing"
void testColorProcessing(Color color, boolean flag) {
System.out.println(color);
System.out.println(flag);
}
// S1144 flags this as unused, but JUnit 5 calls it reflectively
private static Stream<Arguments> testColorProcessing() {
return Stream.of(
Arguments.of(Color.RED, true),
Arguments.of(Color.RED, false),
Arguments.of(Color.GREEN, true),
Arguments.of(Color.GREEN, false),
Arguments.of(Color.BLUE, true),
Arguments.of(Color.BLUE, false)
);
}
}
For comparison, the equivalent explicit form does not trigger S1144:
// BEFORE — no S1144
@ParameterizedTest
@MethodSource("provideParameters")
void testColorProcessing(Color color, boolean flag) { ... }
private static Stream<Arguments> provideParameters() { ... }