In this section, we will explore the @ParameterizedTest annotation in JUnit, which allows us to run the same test multiple times with different parameters. This is particularly useful for testing methods with a variety of inputs and expected outputs.
Key Concepts
- Parameterized Tests: Tests that run multiple times with different sets of parameters.
- @ParameterizedTest Annotation: Marks a method as a parameterized test.
- Source Annotations: Annotations like
@ValueSource,@CsvSource, and@MethodSourcethat provide the parameters for the test.
Setting Up a Parameterized Test
Step-by-Step Guide
- Add JUnit 5 Dependency: Ensure you have JUnit 5 in your project dependencies.
- Create a Test Class: Define a class where you will write your parameterized tests.
- Use @ParameterizedTest: Annotate your test method with
@ParameterizedTest. - Provide Parameters: Use source annotations to provide the parameters for the test.
Example
Let's create a simple parameterized test to check if a number is even.
Step 1: Add JUnit 5 Dependency
Ensure your pom.xml (for Maven) or build.gradle (for Gradle) includes JUnit 5.
Maven:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>Gradle:
Step 2: Create a Test Class
Create a new class for your tests.
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class NumberTest {
@ParameterizedTest
@ValueSource(ints = {2, 4, 6, 8, 10})
void testIsEven(int number) {
assertTrue(isEven(number));
}
boolean isEven(int number) {
return number % 2 == 0;
}
}Explanation
- @ParameterizedTest: Marks the
testIsEvenmethod as a parameterized test. - @ValueSource: Provides the parameters for the test. In this case, it provides an array of integers.
- assertTrue: Asserts that the condition is true. Here, it checks if the number is even.
Using Different Source Annotations
@CsvSource
Use @CsvSource to provide multiple parameters.
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class MathTest {
@ParameterizedTest
@CsvSource({
"1, 1, 2",
"2, 3, 5",
"3, 5, 8"
})
void testAddition(int a, int b, int expected) {
assertEquals(expected, add(a, b));
}
int add(int a, int b) {
return a + b;
}
}Explanation
- @CsvSource: Provides multiple sets of parameters. Each set is a comma-separated string.
- assertEquals: Asserts that the expected value is equal to the actual value.
@MethodSource
Use @MethodSource to provide parameters from a method.
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class StringTest {
@ParameterizedTest
@MethodSource("stringProvider")
void testIsNotEmpty(String str) {
assertTrue(str != null && !str.isEmpty());
}
static Stream<String> stringProvider() {
return Stream.of("apple", "banana", "cherry");
}
}Explanation
- @MethodSource: Specifies a method that provides the parameters. The method must return a
Stream,Iterable,Iterator, or array. - assertTrue: Asserts that the string is not null and not empty.
Practical Exercise
Exercise
Create a parameterized test to check if a string is a palindrome.
- Create a new test class
PalindromeTest. - Write a method
isPalindromethat checks if a string is a palindrome. - Use
@ParameterizedTestand@ValueSourceto test the method with different strings.
Solution
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class PalindromeTest {
@ParameterizedTest
@ValueSource(strings = {"madam", "racecar", "radar"})
void testIsPalindrome(String str) {
assertTrue(isPalindrome(str));
}
boolean isPalindrome(String str) {
return str.equals(new StringBuilder(str).reverse().toString());
}
}Explanation
- @ValueSource: Provides an array of strings to test.
- isPalindrome: Checks if the string is equal to its reverse.
Common Mistakes and Tips
- Incorrect Parameter Types: Ensure the parameter types in the test method match those provided by the source annotation.
- Null Values: Handle null values appropriately in your tests.
- Complex Parameters: For complex parameters, consider using
@MethodSourcefor better readability and maintainability.
Conclusion
In this section, we learned how to use the @ParameterizedTest annotation in JUnit to run tests with different parameters. We explored various source annotations like @ValueSource, @CsvSource, and @MethodSource to provide parameters. By using parameterized tests, we can write more comprehensive and efficient test cases, ensuring our code is robust and reliable.
JUnit Course
Module 1: Introduction to JUnit
Module 2: Basic JUnit Annotations
- Understanding @Test
- Using @Before and @After
- Using @BeforeClass and @AfterClass
- Ignoring Tests with @Ignore
Module 3: Assertions in JUnit
Module 4: Parameterized Tests
- Introduction to Parameterized Tests
- Creating Parameterized Tests
- Using @ParameterizedTest
- Custom Parameterized Tests
Module 5: Test Suites
Module 6: Mocking with JUnit
Module 7: Advanced JUnit Features
Module 8: Best Practices and Tips
- Writing Effective Tests
- Organizing Test Code
- Test-Driven Development (TDD)
- Continuous Integration with JUnit
