@MethodSource helps you run the same test with different data easily. It uses a method that gives test data, so you don't repeat code.
@MethodSource for factory methods in JUnit
@ParameterizedTest @MethodSource("factoryMethodName") void testMethod(Type param) { // test code } static Stream<Type> factoryMethodName() { return Stream.of(data1, data2, ...); }
The factory method must be static and return a Stream, Iterable, Iterator, or array of arguments.
The method name in @MethodSource is a string matching the factory method's name.
@ParameterizedTest @MethodSource("stringProvider") void testWithStrings(String arg) { assertNotNull(arg); } static Stream<String> stringProvider() { return Stream.of("apple", "banana", "cherry"); }
@ParameterizedTest @MethodSource("intProvider") void testWithInts(int number) { assertTrue(number > 0); } static Stream<Integer> intProvider() { return Stream.of(1, 2, 3, 4); }
This test uses @MethodSource to supply three sets of numbers to test the add method of Calculator.
import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.Arguments; import java.util.stream.Stream; public class CalculatorTest { @ParameterizedTest @MethodSource("additionProvider") void testAdd(int a, int b, int expected) { Calculator calc = new Calculator(); assertEquals(expected, calc.add(a, b)); } static Stream<Arguments> additionProvider() { return Stream.of( Arguments.of(1, 1, 2), Arguments.of(2, 3, 5), Arguments.of(10, 20, 30) ); } } class Calculator { int add(int x, int y) { return x + y; } }
Factory methods must be static so JUnit can call them without creating an instance.
You can return multiple parameters using Arguments.of(...) inside the Stream.
Use descriptive method names for clarity in test reports.
@MethodSource lets you run one test with many data sets easily.
Factory methods provide the test data and must be static.
This keeps tests clean and avoids repeating similar test code.
Practice
@MethodSource in JUnit tests?Solution
Step 1: Understand the role of @MethodSource
@MethodSource is used to supply multiple data sets to a single test method, allowing it to run multiple times with different inputs.Step 2: Compare options with this role
Options B, C, and D describe unrelated features. Only To provide multiple sets of data to a single test method correctly describes the purpose of @MethodSource.Final Answer:
To provide multiple sets of data to a single test method -> Option CQuick Check:
@MethodSource = multiple data sets [OK]
- Thinking @MethodSource creates tests automatically
- Confusing @MethodSource with test skipping annotations
- Assuming @MethodSource controls test threading
@MethodSource in JUnit 5?Solution
Step 1: Recall factory method requirements
Factory methods used with @MethodSource must be static and public to be accessible by the test framework.Step 2: Check each option
public static Stream<Arguments> provideData() is public and static, matching requirements. private Stream<Arguments> provideData() is private, so inaccessible. public Stream<Arguments> provideData() is public but not static. static Stream<Arguments> provideData() is static but missing public modifier.Final Answer:
public static Stream<Arguments> provideData() -> Option AQuick Check:
Factory method = public static [OK]
- Omitting static keyword
- Making the method private
- Using wrong return type
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.Arguments;
import java.util.stream.Stream;
public class CalculatorTest {
@ParameterizedTest
@MethodSource("dataProvider")
void testAdd(int a, int b, int expected) {
assertEquals(expected, a + b);
}
static Stream<Arguments> dataProvider() {
return Stream.of(
Arguments.of(1, 2, 3),
Arguments.of(2, 3, 5),
Arguments.of(3, 5, 9)
);
}
}Solution
Step 1: Check each data set against the assertion
First: 1 + 2 = 3 (matches expected 3), second: 2 + 3 = 5 (matches expected 5), third: 3 + 5 = 8 but expected is 9.Step 2: Identify test result
The third test case fails because the expected value is incorrect.Final Answer:
Test fails on the last data set because 3 + 5 != 9 -> Option AQuick Check:
3+5=8 ≠ 9, test fails [OK]
- Assuming all tests pass without checking values
- Ignoring the static keyword correctness
- Confusing compilation and runtime errors
@MethodSource and suggest a fix:import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.Arguments;
import java.util.stream.Stream;
public class SampleTest {
@ParameterizedTest
@MethodSource("numbers")
void testIsPositive(int number) {
assertTrue(number > 0);
}
Stream<Arguments> numbers() {
return Stream.of(
Arguments.of(1),
Arguments.of(2),
Arguments.of(3)
);
}
}Solution
Step 1: Check factory method signature
The method 'numbers' is not static, but factory methods for @MethodSource must be static to be accessible.Step 2: Suggest fix
Make the 'numbers' method static by adding the static keyword.Final Answer:
The factory method 'numbers' must be static -> Option BQuick Check:
Factory method must be static [OK]
- Forgetting static keyword on factory method
- Thinking test methods must return values
- Assuming @MethodSource needs class name always
@MethodSource. The factory method returns a Stream<Arguments> with customer type and expected discount. Which approach correctly handles a case where the discount is zero for unknown customer types without failing the test?Solution
Step 1: Understand test coverage needs
To test all cases including unknown customer types, the factory method should provide data for them explicitly.Step 2: Choose approach that includes zero discount case
Including an Arguments entry with unknown type and expected discount 0 ensures the test runs and verifies correct behavior without failure.Final Answer:
Include an Arguments entry with unknown customer type and expected discount 0 in the factory method -> Option DQuick Check:
Test all cases by including zero discount data [OK]
- Skipping edge cases in factory method
- Expecting exceptions instead of valid results
- Splitting tests unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
