Question
How can I implement JUnit 5 @MethodSource in a nested class for parameterized tests?
@MethodSource("cards")
Answer
To use `@MethodSource` in a nested class while adhering to the JUnit 5 framework's requirements, you can follow these approaches. The core challenge lies in the need for the method providing the arguments to be `static` and the compatibility of nested classes. Below are step-by-step solutions to effectively implement this.
@Nested
static class Cost {
static Stream<Arguments> cards() {
return Stream.of(
Arguments.of(Card.common(0, Color.RED), 0),
Arguments.of(Card.choseColor(), 50)
);
}
@MethodSource("cards")
@ParameterizedTest
void cardCost(Card card, int cost) {
assertThat(card.cost()).isEqualTo(cost);
}
}
Causes
- The `@MethodSource` annotation requires the method supplying the stream of arguments to be static.
- Non-static inner classes in Java cannot have static methods, which leads to a conflict when attempting to use `@MethodSource`.
- If the inner class is made static, JUnit does not recognize it, hindering test execution.
Solutions
- Move the parameter source method to a separate static method in the enclosing class. This enables it to be accessible without breaking the rules of static inner classes.
- Declare the nested class as static which allows the use of static methods inside it while still being recognized by JUnit.
Common Mistakes
Mistake: Declaring the cards() method as non-static in a static nested class.
Solution: Always declare the argument-providing method as static in a nested class.
Mistake: Forgetting to configure JUnit to discover nested tests correctly.
Solution: Ensure the nested class is properly annotated with @Nested and maintain a static context for parameters.
Helpers
- JUnit 5
- @MethodSource
- Nested Class parameterized tests
- Java testing
- JUnit Testing best practices