使用JUnit 5进行更清洁的参数化测试

参数化单元测试的总体思路是对不同的数据运行相同的测试方法。 在JUnit 4中创建参数化测试远非完美。 现有体系结构存在许多问题:将参数定义为类字段,并且需要使用构造函数来创建它们,不能将参数化和非参数化测试混合在一个测试类中,并且内置数据源非常有限。 幸运的是,所有这些都在JUnit 5中得到了改进!

注意:作为JUnit 4参数化测试的替代方法,您可以使用JUnitParams库来解决我提到的许多问题(请在此处查看有关JUnitParams的博客文章: http : //blog.codeleak.pl/2013/12/parametrized-junit- tests-with.html )。

如何开始?

要开始在Junit 5中进行参数化测试,您需要向项目添加必需的依赖项:向项目添加org.junit.jupiter:junit-jupiter-params:${junitJupiterVersion}依赖项以使用参数化测试,参数提供程序和转换器。

SUT –被测系统

我创建的所有示例都在测试FizzBu​​zz类:

public class FizzBuzz {

    private static final int THREE = 3;
    private static final int FIVE = 5;

    public String calculate(int number) {
        if (isDivisibleBy(number, THREE) && isDivisibleBy(number, FIVE)) {
            return "FizzBuzz";
        }

        if (isDivisibleBy(number, THREE)) {
            return "Fizz";
        }

        if (isDivisibleBy(number, FIVE)) {
            return "Buzz";
        }

        return String.valueOf(number);
    }

    private static boolean isDivisibleBy(int dividend, int divisor) {
        return dividend % divisor == 0;
    }
}

尽管FizzBu​​zz非常简单,但是它也可以用于演示更高级的单元测试技术,例如实现参数化测试。

我在JUnit 5中的第一个参数化测试

要在JUnit 5中创建参数化测试,请使用@org.junit.jupiter.params.ParameterizedTest (而不是@Test )注释测试方法,并提供参数来源:

@ParameterizedTest(name = "{index} => calculate({0})")
@ValueSource(ints = {1, 2, 4, 7, 11, 13, 14})
public void returnsNumberForNumberNotDivisibleByThreeAndFive(int number, TestInfo testInfo) {
    assertThat(fizzBuzz.calculate(number)).isEqualTo("" + number);
}

注释具有可选的name属性,用于自定义调用显示名称。 可用的模板变量:{index}->当前调用索引(从1开始),{arguments}->完整的,逗号分隔的参数列表,{0},{1},…->一个单独的参数。

在此示例中, @org.junit.jupiter.params.provider.ValueSource提供对整数文字值数组的访问。 必须在此批注中提供一种输入类型(字符串,实例,长整型或双精度型)。

我还提供了由org.junit.jupiter.api.extension.ParameterResolver解析的其他参数。 请注意,由参数源解析的方法参数需要在参数列表中排在首位。

更多论点来源

@MethodSource

@ParameterizedTest(name = "{index} => calculate({0})")
@MethodSource(names = {"divisibleByThree", "divisibleByThreeButNotFive"})
void returnFizzForNumberDivisibleByThree(int number) {
    assertThat(fizzBuzz.calculate(number)).isEqualTo("Fizz");
}

@org.junit.jupiter.params.provider.MethodSource引用返回自变量源的方法(1个或更多)。 在此示例中,有两种方法:

private static Stream divisibleByThree() {
    int[] ints = new int[]{18, 21};
    return Stream.of(3, 6, 9, 12);
}

// The returned array will be converted to a Stream
private static String[] divisibleByThreeButNotFive() {
    return new String[]{"18", "21"};
}

提供参数的方法必须是静态的,不能包含任何参数,并且必须返回Stream,Iterable,Iterator或数组。 您可能会注意到, divisibleByThreeButNotFive()方法返回一个字符串数组。 由于内置了隐式参数转换器,因此可以很好地工作。 当参数源是CSV时(这在下面有更多说明),这确实很有用。 此外,可以使用自定义参数转换器来转换参数。

要解析多个参数,方法源将返回org.junit.jupiter.params.provider.Arguments实例流( org.junit.jupiter.params.provider.ObjectArrayArguments ):

@ParameterizedTest(name = "{index} => calculate({0}) should return {1}")
@MethodSource(names = {"fizzBuzz"})
void fizzBuzz(int number, String expectedResult) {
    assertThat(fizzBuzz.calculate(number)).isEqualTo(expectedResult);
}

private static Stream fizzBuzz() {
    return Stream.of(
        ObjectArrayArguments.create(1, "1"),
        ObjectArrayArguments.create(2, "2"),
        ObjectArrayArguments.create(3, "Fizz"),
        ObjectArrayArguments.create(4, "4"),
        ObjectArrayArguments.create(5, "Buzz"),
        ObjectArrayArguments.create(6, "Fizz"),
        ObjectArrayArguments.create(7, "7"),
        ObjectArrayArguments.create(8, "8"),
        ObjectArrayArguments.create(9, "Fizz"),
        ObjectArrayArguments.create(15, "FizzBuzz")
    );
}

@CsvFileSource

提供参数源的另一种非常有趣的方法是org.junit.jupiter.params.provider.CsvFileSource ,它从类路径中的多个CSV文件之一中提供参数:

@ParameterizedTest(name = "{index} => calculate({0}) should return {1}")
@CsvFileSource(resources = {"/fizzbuzz/fizzbuzz_1.csv", "/fizzbuzz/fizzbuzz_2.csv"}, delimiter = ';')
void fizzBuzzCsv(int number, String expectedResult) {
    assertThat(fizzBuzz.calculate(number)).isEqualTo(expectedResult);
}

其他论点

  • @EnumSource提供了使用Enum常量的便捷方法。
  • @CsvSource允许您将参数列表表示为以逗号分隔的值
  • @ArgumentsSource可用于指定自定义,可重用的参数提供程序。

享受JUnit 5中的参数化测试!

资源资源

可以在GitHub上找到本文中介绍的所有示例: https : //github.com/kolorobot/unit-testing-demo

查看官方的JUnit 5文档以了解更多信息: http : //junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests

翻译自: https://www.javacodegeeks.com/2017/06/cleaner-parameterized-tests-junit-5.html

你可能感兴趣的:(使用JUnit 5进行更清洁的参数化测试)