How do I use @ValueSource in JUnit parameterized tests?

In JUnit 5, @ValueSource is used with @ParameterizedTest to run the same test multiple times with different simple literal values.

Basic example

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import static org.junit.jupiter.api.Assertions.assertTrue;

class StringTest {

    @ParameterizedTest
    @ValueSource(strings = {"racecar", "radar", "level"})
    void palindromeWordsHaveLengthGreaterThanZero(String word) {
        assertTrue(word.length() > 0);
    }
}

This test runs 3 times, once for each value:

racecar
radar
level

Supported @ValueSource types

@ValueSource supports arrays of simple values such as:

@ValueSource(strings = {"apple", "banana"})
@ValueSource(ints = {1, 2, 3})
@ValueSource(longs = {10L, 20L})
@ValueSource(doubles = {1.5, 2.5})
@ValueSource(booleans = {true, false})
@ValueSource(chars = {'a', 'b'})
@ValueSource(classes = {String.class, Integer.class})

Example with integers:

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import static org.junit.jupiter.api.Assertions.assertTrue;

class NumberTest {

    @ParameterizedTest
    @ValueSource(ints = {2, 4, 6, 8})
    void numbersAreEven(int number) {
        assertTrue(number % 2 == 0);
    }
}

Important limitation

@ValueSource can provide only one argument per test invocation.

So this works:

@ParameterizedTest
@ValueSource(strings = {"hello", "world"})
void testSingleArgument(String value) {
    // test logic
}

But this does not work with @ValueSource:

@ParameterizedTest
@ValueSource(strings = {"hello", "world"})
void testMultipleArguments(String input, int expectedLength) {
    // invalid for @ValueSource
}

For multiple arguments, use @CsvSource, @MethodSource, or @ArgumentsSource.

Example with empty and blank strings

@ValueSource can be combined with other parameter sources:

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EmptySource;
import org.junit.jupiter.params.provider.NullSource;
import org.junit.jupiter.params.provider.ValueSource;

import static org.junit.jupiter.api.Assertions.assertTrue;

class BlankStringTest {

    @ParameterizedTest
    @NullSource
    @EmptySource
    @ValueSource(strings = {" ", "   ", "\t", "\n"})
    void stringIsBlank(String value) {
        assertTrue(value == null || value.isBlank());
    }
}

This runs with:

null
""
" "
"   "
"\t"
"\n"

Maven dependency

Make sure you have JUnit Jupiter Params on the test classpath:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <scope>test</scope>
</dependency>

If you use Spring Boot, this is usually included through:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

Summary

Use @ValueSource when your parameterized test needs one simple value per run:

@ParameterizedTest
@ValueSource(strings = {"a", "b", "c"})
void test(String value) {
    // runs once for each value
}

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.