Java > Testing in Java > Unit Testing > JUnit 5 Basics
Parameterized Tests in JUnit 5
This snippet demonstrates how to use parameterized tests in JUnit 5 to run the same test multiple times with different input values.
Project setup
To begin, ensure you have JUnit 5 added to your project. If you're using Maven, add the following dependency to your pom.xml:
<!-- JUnit 5 Dependency (Maven) -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
Parameterized Test Example
This code snippet shows a parameterized test using JUnit 5. Let's break it down:
ParameterizedTest
annotation, which indicates that the method is a parameterized test.CsvSource
annotation, which provides the input values for the test.testAddition
method is a parameterized test.a
, b
, and expected
. These arguments are automatically populated with the values from the CsvSource
annotation.
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ParameterizedCalculatorTest {
@ParameterizedTest
@CsvSource({"2, 3, 5", "-1, 5, 4", "0, 0, 0"})
void testAddition(int a, int b, int expected) {
SimpleCalculator calculator = new SimpleCalculator();
int result = calculator.add(a, b);
assertEquals(expected, result, "Addition should return the correct sum");
}
}
SimpleCalculator Class (Code Under Test)
This is the same simple calculator class from the previous example. The parameterized test verifies that its add
method correctly adds two integers for multiple input values.
public class SimpleCalculator {
public int add(int a, int b) {
return a + b;
}
}
Concepts Behind the Snippet
Parameterized tests are useful when you want to test the same code with multiple sets of input values. This can save time and reduce code duplication compared to writing separate test methods for each set of inputs. JUnit 5's @ParameterizedTest
and @CsvSource
annotations make it easy to define and run parameterized tests.
Real-Life Use Case
Consider validating user input. You might want to test a method that validates email addresses with various valid and invalid email address formats. A parameterized test would allow you to easily define a set of email addresses and their expected validation results, running the same validation logic for each case.
Best Practices
@CsvSource
, @ValueSource
, @MethodSource
, and @EnumSource
. Choose the one that best suits your needs.name
attribute of the @ParameterizedTest
annotation to provide meaningful names for each test execution.
Interview Tip
Be prepared to explain the benefits of parameterized testing (reduced code duplication, increased test coverage) and to provide examples of when you would use them.
When to Use Them
Use parameterized tests when you need to test the same code with multiple sets of input values, especially when the logic is relatively simple and the variations are in the inputs.
Alternatives
Instead of parameterized tests, you could write separate test methods for each set of input values. However, this can lead to code duplication and make the tests harder to maintain.
Pros
Cons
FAQ
-
What is the purpose of the @CsvSource annotation?
The@CsvSource
annotation provides input values for the parameterized test in the form of comma-separated values. Each string in the@CsvSource
annotation represents a set of input values for a single execution of the test. -
What other data source annotations are available in JUnit 5 for parameterized tests?
Besides@CsvSource
, JUnit 5 offers@ValueSource
(for single-value parameters),@MethodSource
(for providing values from a method), and@EnumSource
(for providing values from an enum). -
How can I provide more complex input values for a parameterized test?
For more complex input values, you can use the@MethodSource
annotation and provide a method that returns a stream of arguments. This allows you to create custom objects or data structures for each test execution.