JUnit @ParameterizedTest with @MethodSource

JUnit is a popular testing framework in the Java ecosystem that simplifies writing and running tests. The @ParameterizedTest annotation in JUnit is used to run the same test with different inputs. This guide covers the basics of using the @ParameterizedTest annotation with @MethodSource to write parameterized tests in JUnit.

Table of Contents

  1. Introduction
  2. Steps to Create a JUnit Parameterized Test
  3. Real-World Use Case
  4. Conclusion

Introduction

The @ParameterizedTest annotation marks methods that should be executed multiple times with different parameters. The @MethodSource annotation is used to provide a method as the source of the parameters for the parameterized test.

Steps to Create a JUnit Parameterized Test

Step 1: Add Maven Dependency

To use JUnit in your project, you need to add the JUnit dependency to your pom.xml file. Use the latest version of JUnit 5:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.9.2</version>
    <scope>test</scope>
</dependency>

Step 2: Create the Class to be Tested

Create a Java class with methods that you want to test. For example, a simple MathUtils class:

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

    public int subtract(int a, int b) {
        return a - b;
    }
}

Step 3: Create the Parameterized Test Class

Create a test class in the src/test/java directory. Use the @ParameterizedTest annotation and specify the source of the parameters using @MethodSource.

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 {
    private final MathUtils mathUtils = new MathUtils();

    static Stream<int[]> provideAdditionArguments() {
        return Stream.of(
            new int[]{1, 2, 3},
            new int[]{2, 3, 5},
            new int[]{3, 4, 7},
            new int[]{4, 5, 9}
        );
    }

    @ParameterizedTest
    @MethodSource("provideAdditionArguments")
    void testAddition(int[] args) {
        int a = args[0];
        int b = args[1];
        int expected = args[2];
        assertEquals(expected, mathUtils.add(a, b), a + " + " + b + " should equal " + expected);
    }
}

In this example, the provideAdditionArguments method returns a Stream of integer arrays, each containing a set of parameters for the test. The testAddition method is annotated with @ParameterizedTest and uses @MethodSource to provide the parameter sets.

Step 4: Run the Test

You can run the test using your IDE, Maven, or Gradle.

Using an IDE:

Most IDEs, like IntelliJ IDEA and Eclipse, have built-in support for running JUnit tests. Simply right-click on your test class or method and select “Run.”

Using Maven:

If you’re using Maven, you can run your tests with the following command:

mvn test

Using Gradle:

If you’re using Gradle, you can run your tests with the following command:

gradle test

Real-World Use Case

In real-world applications, you may need to test methods with various inputs. For instance, a StringUtils class might need to be tested with different string inputs to ensure correct behavior.

Create the Class to be Tested

Create a Java class that contains business logic. For example, a StringUtils class that reverses strings:

public class StringUtils {
    public String reverse(String str) {
        if (str == null) {
            return null;
        }
        return new StringBuilder(str).reverse().toString();
    }
}

In this class, the reverse method reverses a given string.

Create the Parameterized Test Class

Create a test class for the StringUtils in the src/test/java directory. Use the @ParameterizedTest annotation and @MethodSource to provide different string inputs and expected results:

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 StringUtilsTest {
    private final StringUtils stringUtils = new StringUtils();

    static Stream<String[]> provideReverseArguments() {
        return Stream.of(
            new String[]{"hello", "olleh"},
            new String[]{"world", "dlrow"},
            new String[]{"java", "avaj"},
            new String[]{"", ""},
            new String[]{null, null}
        );
    }

    @ParameterizedTest
    @MethodSource("provideReverseArguments")
    void testReverse(String[] args) {
        String input = args[0];
        String expected = args[1];
        assertEquals(expected, stringUtils.reverse(input), "Reversing '" + input + "' should give '" + expected + "'");
    }
}

In this test class, the provideReverseArguments method returns a Stream of string arrays, each containing a set of parameters for the test. The testReverse method is annotated with @ParameterizedTest and uses @MethodSource to provide the parameter sets.

Running the Tests

You can run the tests using your IDE, Maven, or Gradle.

Using an IDE:

Most IDEs, like IntelliJ IDEA and Eclipse, have built-in support for running JUnit tests. Simply right-click on your test class or method and select “Run.”

Using Maven:

If you’re using Maven, you can run your tests with the following command:

mvn test

Using Gradle:

If you’re using Gradle, you can run your tests with the following command:

gradle test

Conclusion

The @ParameterizedTest annotation in JUnit makes it easy to run the same test with different inputs. By using @ParameterizedTest with @MethodSource, you can ensure that your methods behave correctly with various inputs without writing multiple test cases.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top