Author

Author- Ram Ranjeet Kumar

Saturday, August 12, 2023

@MethodSource Annotation With @ParameterizedTest in JUnit5



  • The @MethodSource annotation is a part of the JUnit 5 testing framework in Java.
  •  It is used to specify a method as the source of test cases for parameterized tests. 
  • Parameterized tests allow you to run the same test logic with multiple sets of input parameters, making your testing more comprehensive and efficient.
  • The @MethodSource annotation is used to indicate that the source of test cases for a parameterized test method comes from another method. 
  • This annotation is applied to the parameterized test method itself.
  • @MethodSource is an annotation that allows you to provide arguments for a parameterized test from a factory method.
  • The factory method can be in the same class as the test or in an external class. 
  • The factory method must return a stream, iterable, iterator, or array of arguments. 

Example:
Let's say you have a simple class called MathUtils with a method add(int a, int b) that adds two integers

public class MathUtils {
    public static int add(int a, int b) {
        return a + b;
    }
}

Now, you want to write parameterized tests for the add method using JUnit 5 and the @MethodSource annotation.
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.assertEquals;

public class MathUtilsTest {

    @ParameterizedTest
    @MethodSource("additionProvider")
    void testAddition(int a, int b, int expectedResult) {
        int result = MathUtils.add(a, b);
        assertEquals(expectedResult, result);
    }

    static Stream<Arguments> additionProvider() {
        return Stream.of(
            Arguments.of(2, 3, 5),
            Arguments.of(-1, 1, 0),
            Arguments.of(0, 0, 0)
        );
    }
}

In this example:
  • The testAddition method is a parameterized test method that takes three parameters: a, b, and expectedResult.
  • The @MethodSource("additionProvider") annotation specifies that the test cases will be provided by the method named additionProvider.
  • The additionProvider method returns a Stream<Arguments> containing sets of arguments for the parameterized test.
  • When you run the tests, JUnit 5 will generate separate test cases for each set of arguments provided by the additionProvider method. 
  • This way, you can easily test the add method with various input values without writing multiple individual test methods.

Let's consider another example using a different data type. Suppose you have a class called StringUtils with a method concatenate(String a, String b) that concatenates two strings

public class StringUtils {
    public static String concatenate(String a, String b) {
        return a + b;
    }
}

Now, you want to write parameterized tests for the concatenate method using JUnit 5 and the @MethodSource annotation.

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.stream.Stream;

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

public class StringUtilsTest {

    @ParameterizedTest
    @MethodSource("concatenationProvider")
    void testConcatenation(String a, String b, String expectedResult) {
        String result = StringUtils.concatenate(a, b);
        assertEquals(expectedResult, result);
    }

    static Stream<Arguments> concatenationProvider() {
        return Stream.of(
            Arguments.of("Hello, ", "world!", "Hello, world!"),
            Arguments.of("", "Test", "Test"),
            Arguments.of("Java ", "Programming", "Java Programming")
        );
    }
}


In this example:

  • The testConcatenation method is a parameterized test method that takes three parameters: a, b, and expectedResult.
  • The @MethodSource("concatenationProvider") annotation specifies that the test cases will be provided by the method named concatenationProvider.
  • The concatenationProvider method returns a Stream<Arguments> containing sets of arguments for the parameterized test.
  • When you run the tests, JUnit 5 will generate separate test cases for each set of arguments provided by the concatenationProvider method. This allows you to test the concatenate method with various combinations of strings without writing repetitive test code.

Here is an example of using @MethodSource annotation with an iterable:

@ParameterizedTest
@MethodSource("provideStringsForIsBlank")
void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input, boolean expected) {
    assertEquals(expected, Strings.isBlank(input));
}

static Stream<Arguments> provideStringsForIsBlank() {
    return Stream.of(
      Arguments.of(null, true),
      Arguments.of("", true),
      Arguments.of("  ", true),
      Arguments.of("not blank", false)
    );
}

Here is an example of using @MethodSource annotation with an iterator:

@ParameterizedTest
@MethodSource("provideIntegers")
void testWithIteratorSource(int argument) {
    assertNotEquals(9, argument);
}

static Iterator<Integer> provideIntegers() {
    return Arrays.asList(1, 2, 3, 4, 5).iterator();
}

Here is an example of using @MethodSource annotation with an array:

@ParameterizedTest
@MethodSource("provideStrings")
void testWithArraySource(String argument) {
    assertNotNull(argument);
}

static String[] provideStrings() {
    return new String[] {"hello", "world"};
}

Remember to add the appropriate JUnit 5 dependencies to your project to use these annotations and features.


No comments:

Post a Comment