SUGGESTION
Simplification
View source code on GitHub
Summary Prefer @ValueSource over a @MethodSource where possible and reasonable
Summary
Prefer @ValueSource over a @MethodSource where possible and reasonable
@ValueSource
@MethodSource
Suppression Suppress false positives by adding the suppression annotation @SuppressWarnings("JUnitValueSource") to the enclosing element. Disable this pattern completely by adding -Xep:JUnitValueSource:OFF as compiler argument. Learn more.
Suppression
Suppress false positives by adding the suppression annotation @SuppressWarnings("JUnitValueSource") to the enclosing element.
@SuppressWarnings("JUnitValueSource")
Disable this pattern completely by adding -Xep:JUnitValueSource:OFF as compiler argument. Learn more.
-Xep:JUnitValueSource:OFF
Shows the difference in example code before and after the bug pattern is applied.
import static org.junit.jupiter.params.provider.Arguments.arguments; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import java.util.List; import java.util.Set; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; class A { private static final boolean CONST_BOOLEAN = false; private static final byte CONST_BYTE = 42; private static final char CONST_CHARACTER = 'a'; private static final short CONST_SHORT = 42; private static final int CONST_INTEGER = 42; private static final long CONST_LONG = 42; private static final float CONST_FLOAT = 42; private static final double CONST_DOUBLE = 42; private static final String CONST_STRING = "foo"; - private static Stream<Arguments> streamOfBooleanArguments() { - return Stream.of(arguments(false), arguments(true), arguments(CONST_BOOLEAN)); - } - @ParameterizedTest - @MethodSource("streamOfBooleanArguments") + @ValueSource(booleans = {false, true, CONST_BOOLEAN}) void primitiveBoolean(boolean b) {} - private static Stream<Object> streamOfBooleansAndBooleanArguments() { - return Stream.of(false, arguments(true), CONST_BOOLEAN); - } - @ParameterizedTest - @MethodSource("streamOfBooleansAndBooleanArguments") + @ValueSource(booleans = {false, true, CONST_BOOLEAN}) void boxedBoolean(Boolean b) {} - private static List<Arguments> listOfByteArguments() { - return List.of(arguments((byte) 0), arguments((byte) 1), arguments(CONST_BYTE)); - } - @ParameterizedTest - @MethodSource("listOfByteArguments") + @ValueSource(bytes = {(byte) 0, (byte) 1, CONST_BYTE}) void primitiveByte(byte b) {} - private static List<Object> listOfBytesAndByteArguments() { - return List.of((byte) 0, arguments((byte) 1), CONST_BYTE); - } - @ParameterizedTest - @MethodSource("listOfBytesAndByteArguments") + @ValueSource(bytes = {(byte) 0, (byte) 1, CONST_BYTE}) void boxedByte(Byte b) {} - private static Set<Arguments> setOfCharacterArguments() { - return Set.of(arguments((char) 0), arguments((char) 1), arguments(CONST_CHARACTER)); - } - @ParameterizedTest - @MethodSource("setOfCharacterArguments") + @ValueSource(chars = {(char) 0, (char) 1, CONST_CHARACTER}) void primitiveCharacter(char c) {} - private static Set<Object> setOfCharactersAndCharacterArguments() { - return Set.of((char) 0, arguments((char) 1), CONST_CHARACTER); - } - @ParameterizedTest - @MethodSource("setOfCharactersAndCharacterArguments") + @ValueSource(chars = {(char) 0, (char) 1, CONST_CHARACTER}) void boxedCharacter(Character c) {} - private static Arguments[] arrayOfShortArguments() { - return new Arguments[] {arguments((short) 0), arguments((short) 1), arguments(CONST_SHORT)}; - } - @ParameterizedTest - @MethodSource("arrayOfShortArguments") + @ValueSource(shorts = {(short) 0, (short) 1, CONST_SHORT}) void primitiveShort(short s) {} - private static Object[] arrayOfShortsAndShortArguments() { - return new Object[] {(short) 0, arguments((short) 1), CONST_SHORT}; - } - @ParameterizedTest - @MethodSource("arrayOfShortsAndShortArguments") + @ValueSource(shorts = {(short) 0, (short) 1, CONST_SHORT}) void boxedShort(Short s) {} - private static IntStream intStream() { - return IntStream.of(0, 1, CONST_INTEGER); - } - @ParameterizedTest - @MethodSource("intStream") + @ValueSource(ints = {0, 1, CONST_INTEGER}) void primitiveInteger(int i) {} - private static int[] intArray() { - return new int[] {0, 1, CONST_INTEGER}; - } - @ParameterizedTest - @MethodSource("intArray") + @ValueSource(ints = {0, 1, CONST_INTEGER}) void boxedInteger(Integer i) {} - private static LongStream longStream() { - return LongStream.of(0, 1, CONST_LONG); - } - @ParameterizedTest - @MethodSource("longStream") + @ValueSource(longs = {0, 1, CONST_LONG}) void primitiveLong(long l) {} - private static long[] longArray() { - return new long[] {0, 1, CONST_LONG}; - } - @ParameterizedTest - @MethodSource("longArray") + @ValueSource(longs = {0, 1, CONST_LONG}) void boxedLong(Long l) {} - private static ImmutableList<Arguments> immutableListOfFloatArguments() { - return ImmutableList.of(arguments(0.0F), arguments(1.0F), arguments(CONST_FLOAT)); - } - @ParameterizedTest - @MethodSource("immutableListOfFloatArguments") + @ValueSource(floats = {0.0F, 1.0F, CONST_FLOAT}) void primitiveFloat(float f) {} - private static Stream<Object> streamOfFloatsAndFloatArguments() { - return Stream.of(0.0F, arguments(1.0F), CONST_FLOAT); - } - @ParameterizedTest - @MethodSource("streamOfFloatsAndFloatArguments") + @ValueSource(floats = {0.0F, 1.0F, CONST_FLOAT}) void boxedFloat(Float f) {} - private static DoubleStream doubleStream() { - return DoubleStream.of(0, 1, CONST_DOUBLE); - } - @ParameterizedTest - @MethodSource("doubleStream") + @ValueSource(doubles = {0, 1, CONST_DOUBLE}) void primitiveDouble(double d) {} - private static double[] doubleArray() { - return new double[] {0, 1, CONST_DOUBLE}; - } - @ParameterizedTest - @MethodSource("doubleArray") + @ValueSource(doubles = {0, 1, CONST_DOUBLE}) void boxedDouble(Double d) {} - private static ImmutableSet<Arguments> immutableSetOfStringArguments() { - return ImmutableSet.of(arguments("foo"), arguments("bar"), arguments(CONST_STRING)); - } - @ParameterizedTest - @MethodSource("immutableSetOfStringArguments") + @ValueSource(strings = {"foo", "bar", CONST_STRING}) void string(String s) {} - private static Stream<Class<?>> streamOfClasses() { - return Stream.of(Stream.class, java.util.Map.class); - } - @ParameterizedTest - @MethodSource("streamOfClasses") + @ValueSource(classes = {Stream.class, java.util.Map.class}) void clazz(Class<?> c) {} - private static Stream<Arguments> sameNameFactoryTestCases() { - return Stream.of(arguments(1)); - } - private static Stream<Arguments> sameNameFactoryTestCases(int overload) { return Stream.of(arguments(overload)); } @ParameterizedTest - @MethodSource("sameNameFactoryTestCases") + @ValueSource(ints = 1) void sameNameFactory(int i) {} }
Shows code lines which will (not) be flagged by this bug pattern. A //BUG: Diagnostic contains: comment is placed above any violating line.
//BUG: Diagnostic contains:
import static org.junit.jupiter.params.provider.Arguments.arguments; import java.util.Optional; import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; class A { private static Stream<Arguments> identificationTestCases() { return Stream.of(arguments(1), Arguments.of(2)); } @ParameterizedTest // BUG: Diagnostic contains: @MethodSource("identificationTestCases") void identification(int foo) {} private static int[] identificationWithParensTestCases() { return new int[] {1, 2}; } @ParameterizedTest // BUG: Diagnostic contains: @MethodSource("identificationWithParensTestCases()") void identificationWithParens(int foo) {} @ParameterizedTest @MethodSource("valueFactoryMissingTestCases") void valueFactoryMissing(int foo) {} private static Stream<Arguments> multipleUsagesTestCases() { return Stream.of(arguments(1), Arguments.of(2)); } @ParameterizedTest @MethodSource("multipleUsagesTestCases") void multipleUsages1(int foo) {} @ParameterizedTest @MethodSource("multipleUsagesTestCases()") void multipleUsages2(int bar) {} private static Stream<Arguments> valueFactoryRepeatedTestCases() { return Stream.of(arguments(1), arguments(2)); } @ParameterizedTest @MethodSource({"valueFactoryRepeatedTestCases", "valueFactoryRepeatedTestCases"}) void valueFactoryRepeated(int foo) {} private static Stream<Arguments> multipleParametersTestCases() { return Stream.of(arguments(1, 2), arguments(3, 4)); } @ParameterizedTest @MethodSource("multipleParametersTestCases") void multipleParameters(int first, int second) {} private static int[] arrayWithoutInitializersTestCases() { return new int[1]; } @ParameterizedTest @MethodSource("arrayWithoutInitializersTestCases") void arrayWithoutInitializers(int foo) {} private static Stream<Arguments> runtimeValueTestCases() { int second = 2; return Stream.of(arguments(1), arguments(second)); } @ParameterizedTest @MethodSource("runtimeValueTestCases") void runtimeValue(int foo) {} private static Stream<Arguments> streamChainTestCases() { return Stream.of(1, 2).map(Arguments::arguments); } @ParameterizedTest @MethodSource("streamChainTestCases") void streamChain(int number) {} private static Stream<Arguments> multipleReturnsTestCases() { if (true) { return Stream.of(arguments(1), arguments(2)); } else { return Stream.of(arguments(3), arguments(4)); } } @ParameterizedTest @MethodSource("multipleReturnsTestCases") void multipleReturns(int number) {} private static Stream<Arguments> multipleFactoriesFooTestCases() { return Stream.of(arguments(1)); } private static Stream<Arguments> multipleFactoriesBarTestCases() { return Stream.of(arguments(1)); } @ParameterizedTest @MethodSource({"multipleFactoriesFooTestCases", "multipleFactoriesBarTestCases"}) void multipleFactories(int i) {} private static Stream<Arguments> extraArgsTestCases() { return Stream.of(arguments(1), arguments(1, 2)); } @ParameterizedTest @MethodSource("extraArgsTestCases") void extraArgs(int... i) {} private static Stream<Arguments> localClassTestCases() { class Foo { Stream<Arguments> foo() { return Stream.of(arguments(1), arguments(2)); } } return Stream.of(arguments(1), arguments(2)); } @ParameterizedTest // BUG: Diagnostic contains: @MethodSource("localClassTestCases") void localClass(int i) {} private static Stream<Arguments> lambdaReturnTestCases() { int foo = Optional.of(10) .map( i -> { return i / 2; }) .orElse(0); return Stream.of(arguments(1), arguments(1)); } @ParameterizedTest // BUG: Diagnostic contains: @MethodSource("lambdaReturnTestCases") void lambdaReturn(int i) {} @ParameterizedTest @MethodSource("tech.picnic.errorprone.Foo#fooTestCases") void staticMethodReference(int foo) {} private static Stream<Arguments> valueFactoryWithArgumentTestCases(int amount) { return Stream.of(arguments(1), arguments(2)); } @ParameterizedTest // BUG: Diagnostic contains: @MethodSource("valueFactoryWithArgumentTestCases") void valueFactoryWithArgument(int foo) {} private static Arguments[] emptyArrayValueFactoryTestCases() { return new Arguments[] {}; } @ParameterizedTest @MethodSource("emptyArrayValueFactoryTestCases") void emptyArrayValueFactory(int foo) {} private static Stream<Arguments> emptyStreamValueFactoryTestCases() { return Stream.of(); } @ParameterizedTest @MethodSource("emptyStreamValueFactoryTestCases") void emptyStreamValueFactory(int foo) {} private static Arguments[] invalidValueFactoryArgumentsTestCases() { return new Arguments[] {arguments(1), arguments(new Object() {})}; } @ParameterizedTest @MethodSource("invalidValueFactoryArgumentsTestCases") void invalidValueFactoryArguments(int foo) {} }