Skip to content

Junit5参数化用例(三)

JUnit5 参数化用例(三)

JUnit5 枚举参数的参数化

在 JUnit 5 中,可以使用自定义的参数源或内置的参数提供器来实现枚举参数的参数化测试。使用枚举类可以用于标记测试结果状态、定义测试数据、定义测试配置参数等情况。

如何实现枚举参数的参数化:

  1. 定义枚举类
  2. 对测试方法添加 ParameterizedTest 注解以及 EnumSource 注解
  3. 测试方法的形参声明类型是定义的枚举类

枚举参数化注解-简单使用

  1. 需要添加@EnumSource注解
  2. 测试方法传入枚举类作为参数
/**
 * @Author: 霍格沃兹测试开发学社
 * @Desc: '更多测试开发技术探讨,请访问:https://ceshiren.com/t/topic/15860'
 */
package com.hogwarts.JUnit5params;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import java.util.EnumSet;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class EnumTest {
    // 创建一个枚举类
    public enum HogwartsUnit {
        Harry("Harry", 18),
        AD("AD", 19);
        private final String name;
        private final Integer age;
        private HogwartsUnit(String name, Integer age){
            this.name = name;
            this.age = age;
        }
    }
    // @ParameterizedTest 注解指明为参数化测试用例
    @ParameterizedTest
    // @EnumSource 注解表示使用枚举类型
    @EnumSource
    // 枚举类作为参数传入测试方法
    void testWithEnumSourceInclude(HogwartsUnit unit) {
        assertTrue(EnumSet.of(HogwartsUnit.Harry, HogwartsUnit.AD).contains(unit));
    }
}
  • 注意测试方法的形参声明类型应是定义的枚举类
  • 枚举类中的数据对象与测试方法中的对象以及测试结果是一一对应的。

枚举参数化其他规则

1. 使用 names 参数指定枚举对象范围

如果枚举类中的枚举对象很多,但仅需要执行某个枚举对象,可以通过 names 参数指定枚举值

  • 使用格式
 @EnumSource(names = {"Harry"})//引号中替换枚举对象
  • 代码实例
/**
 * @Author: 霍格沃兹测试开发学社
 * @Desc: '更多测试开发技术探讨,请访问:https://ceshiren.com/t/topic/15860'
 */
package junit5.params;

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

import java.util.EnumSet;

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

public class EnumTest {
    // 1. 定义枚举类
    public enum HogwartsUnit {
        Harry("Harry", 18),
        AD("AD", 19);
        private final String name;
        private final Integer age;
        private HogwartsUnit(String name, Integer age){
            this.name = name;
            this.age = age;
        }
    }
    // 2. 对测试方法添加 ParameterizedTest 注解以及EnumSource 注解
    @ParameterizedTest
    // @EnumSource 注解表示使用枚举类型
    @EnumSource(names = {"Harry"})
    // 3. 测试方法的形参声明类型是定义的枚举类
    void testWithEnumSourceInclude(HogwartsUnit unit) {
        assertTrue(EnumSet.of(HogwartsUnit.Harry, HogwartsUnit.AD).contains(unit));
    }
}
  • 我们在测试方法中传入了两个参数,但是由于使用@EnumSource(names = {"Harry"})指定了使用的枚举值,所以在测试时仅执行了一次。

2. 使用 mode 参数指定规则
  • EXCLUDE 代表取反,即指定名称不等于的场景,names 里面指定的内容将不会被执行。
  • MATCH_ALL 代表通过正则进行匹配, names 里面填写正则表达式,如果正则表达式和枚举类对象匹配,则使用此枚举对象。
package junit5.params;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import java.util.EnumSet;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.params.provider.EnumSource.Mode.EXCLUDE;
import static org.junit.jupiter.params.provider.EnumSource.Mode.MATCH_ALL;

public class EnumTest {
    // 创建一个枚举类
    public enum HogwartsUnit {
        Harry("Harry", 18),
        AD("AD", 19);
        private final String name;
        private final Integer age;
        private HogwartsUnit(String name, Integer age){
            this.name = name;
            this.age = age;
        }
    }
    @ParameterizedTest
    // @EnumSource 注解表示使用枚举类型,
    // 通过 mode 参数指定规则
    // mode 值为 EXCLUDE 代表取反,即指定名称不为Harry的枚举值
    @EnumSource(mode = EXCLUDE, names = {"Harry"})
        // 枚举类作为参数传入测试方法
    void testWithEnumSourceExclude(HogwartsUnit unit) {
        assertTrue(EnumSet.of(HogwartsUnit.Harry, HogwartsUnit.AD).contains(unit));
    }
    @ParameterizedTest
    // @EnumSource 注解表示使用枚举类型,
    // 通过 mode 参数指定规则
    // mode 值为 MATCH_ALL,names里面填写正则表达式,如果正则表达式和枚举类对象匹配,则使用此枚举对象。
    @EnumSource(mode = MATCH_ALL, names = {".*ry"})
        // 枚举类作为参数传入测试方法
    void testWithEnumSourceRegex(HogwartsUnit unit) {
        assertTrue(unit.name().endsWith("ry"));
    }
}
  • testWithEnumSourceExclude方法的 mode 值为 EXCLUDE,names 里面指定的内容将不会被执行
  • testWithEnumSourceRegex方法的 mode 值为 MATCH_ALL,names 里面填写正则表达式,如果正则表达式和枚举类对象匹配,则使用此枚举对象。

JUnit5 特殊参数的参数化

在讲解@ValueSource 的使用方法事提到过,@ValueSource 不允许传入 Null 值和 Empty 值。从 JUnit 5.4 开始,我们可以使用@NullSource、@EmptySource 和 @NullAndEmptySource 注解可以分别将单个 null 值、单个 Empty 和 Null 和 Empty 传递给参数化测试方法。

接下来我们看一下这些特殊的参数化是如何使用的。

  • null 参数的参数化注解 @NullSource 注解
  • 参数为空的参数化注解 @EmptySource 注解
  • 需要 null 和空都进行参数化,使用 @NullAndEmptySource 注解
  • 还有其他参数可以用@ValueSource 继续提供

特殊的参数化示例
1. @NullSource
  • 代码实例
// 1.@ParameterizedTest 注解指明为参数化测试用例
@ParameterizedTest
// 2.@NullSource 注解表示使用null参数进行测试输入
@NullSource
// 3.定义一个String 类型的形参
void testNullSource(String param) {
    // 断言入参为null
    System.out.println(param);
    assertNull(param);
}
  • 测试的执行结果与预期结果一致,使用@NullSource 传入单个 null 值,使用 assertNull 进行断言,断言正确。
2. @EmptySource
  • 代码实例
// 1.@ParameterizedTest 注解指明为参数化测试用例
@ParameterizedTest
// 2.@EmptySource 注解表示使用Empty参数进行测试输入
@EmptySource
// 3.定义一个String 类型的形参
void testEmptySource(String param) {
    // 断言参数为Empty
    assertTrue(param.isEmpty());
}
  • 测试的执行结果与预期结果一致,使用@EmptySource 传入单个 Empty,使用 assertTrue(param.isEmpty())进行断言,断言正确。
3. @EmptySource
  • 代码实例
// 1.@ParameterizedTest 注解指明为参数化测试用例
@ParameterizedTest
// 2.@NullAndEmptySource 注解结合了 @EmptySource 与 @NullSource
@NullAndEmptySource
// 3.定义一个String 类型的形参
void testEmptyNullSource(String param) {
    // 断言参数是空的
    assertTrue(param == null || param.isEmpty());
}
  • 测试的执行结果与预期结果一致,使用@NullAndEmptySource 传入 Null 和 Empty,下方测试结果可以看出传入参数实为 null 和空值。
4. @EmptySource 结合 @ValueSource
  • 代码实例
// 1.@ParameterizedTest 注解指明为参数化测试用例
@ParameterizedTest
// 2.@NullAndEmptySource 注解结合了 @EmptySource 与 @NullSource
@NullAndEmptySource
// 3.如果还有其他参数可以用@ValueSource继续提供
@ValueSource(strings = {"张三","李四"})
// 4.定义一个String 类型的形参
void testEmptyNullAndValueSource(String param) {
    // 断言参数是空的
    assertTrue(param == null || param.isEmpty());
}
  • 测试的执行结果与预期结果一致,使用@NullAndEmptySource 传入 Null 和 Empty,配合@ValueSource()提供其他参数。
  • 全部代码
package junit5.params;

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

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

public class EmptyTest {

    // 1.@ParameterizedTest 注解指明为参数化测试用例
    @ParameterizedTest
    // 2.@NullSource 注解表示使用null参数进行测试输入
    @NullSource
    // 3.定义一个String 类型的形参
    void testNullSource(String param) {
        // 断言入参为null
        System.out.println(param);
        assertNull(param);
    }


    // 1.@ParameterizedTest 注解指明为参数化测试用例
    @ParameterizedTest
    // 2.@EmptySource 注解表示使用Empty参数进行测试输入
    @EmptySource
    // 3.定义一个String 类型的形参
    void testEmptySource(String param) {
        // 断言参数为Empty
        assertTrue(param.isEmpty());
    }



    // 1.@ParameterizedTest 注解指明为参数化测试用例
    @ParameterizedTest
    // 2.@NullAndEmptySource 注解结合了 @EmptySource 与 @NullSource
    @NullAndEmptySource
    // 3.定义一个String 类型的形参
    void testEmptyNullSource(String param) {
        // 断言参数是空的
        assertTrue(param == null || param.isEmpty());
    }

    // 1.@ParameterizedTest 注解指明为参数化测试用例
    @ParameterizedTest
    // 2.@NullAndEmptySource 注解结合了 @EmptySource 与 @NullSource
    @NullAndEmptySource
    // 3.如果还有其他参数可以用@ValueSource继续提供
    @ValueSource(strings = {"张三","李四"})
    // 4.定义一个String 类型的形参
    void testEmptyNullAndValueSource(String param) {
        // 断言参数是空的
        assertTrue(param == null || param.isEmpty());
    }
}