本系列文章将学习使用Junit5框架设计单元测试用例,单元测试是很多开发人员不愿意写也无意识操作的事情。但是经过实践发现,单元测试的编写不仅仅可以充分拆解代码逻辑,并且对于代码设计,代码质量把控有着很积极的意义
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.5.2</version>
</dependency>
@Test声明方法为单元测试方法,如果单元测试方法需要通过执行多次不同参数达到某种测验效果则需要使用@ParameterizedTest注解。意思就是这个注解相当于参数单元测试的元注解,当然,如果想顺利进行参数单元测试,还需要系列参数来源支撑
将@ValueSource注解中的属性值赋予测试方法参数,执行测试方法。@ValueSource注解中内置所有支持参数类型的数组属性
序列 | 支持参数类型 | 对应注解属性 |
---|---|---|
1 | 八种基本类型 | chars bytes shorts ints longs floats doucles booleans |
2 | String字符串 | strings |
3 | Class类实例 | classes |
@ParameterizedTest
@ValueSource(strings = {"1","2","3"})
public void parameterizedValueSourceTest(String params){
System.out.println(params);
}
边界值测试中很重要的一项就是非空测试,校验空值情况下程序是否可以正常运行不抛出异常。直白点就是检验接口是否入参空值做处理,Junit5中提供注解@NullSource与@EmptySource支撑该操作
@ParameterizedTest
@NullSource
@EmptySource
public void parameterizedNullAndEmptySourceTest(String nullSource){
System.out.println(nullSource.length());
}
Junit5中提供该注解作为@NullSource与@EmptySource注解的合集,也就是同时具备这俩注解效果
参数对象若为枚举对象,则可以使用注解@EnumSource完成测试。该注解将默认调用枚举类中所有实例进行测试,但是也有相应的参数进行限制
序列 | 属性名 | 属性说明 |
---|---|---|
1 | value | 本次入参枚举类class对象 |
2 | names | 本次入参枚举类中实例对象名称 |
3 | mod | INCLUDE、EXCLUDE限制names属性值为包含列举对象还是祛除names列举对象,MATCH_ALL、MATCH_ANY则是解析names属性中的正则表达式匹配枚举类所有实例的名称 |
序列 | 属性值 | 属性值说明 |
---|---|---|
1 | INCLUDE | 默认属性值,表示包含names属性值列举对象 |
2 | EXCLUDE | 表示祛除names属性值列举对象 |
3 | MATCH_ALL | 符合所有names属性列举正则规则的枚举实例 |
4 | MATCH_ANY | 符合一个names属性列举正则规则即可的枚举实例 |
@ParameterizedTest
@EnumSource(value = TimeUnit.class,mode = EnumSource.Mode.INCLUDE,names = {"DAYS","SECONDS"})
public void parameterizedEnumSourceTest(TimeUnit timeUnit){
System.out.println(timeUnit);
}
@ParameterizedTest
@EnumSource(value = TimeUnit.class,mode = EnumSource.Mode.MATCH_ANY,names = {"^(M|N).+SECONDS$","SECONDS"})
public void parameterizedEnumSourceTest(TimeUnit timeUnit){
System.out.println(timeUnit);
}
工厂类返回一个Stream流,将流解析与单元测试方法参数进行绑定,完成参数测试。注意一点就是如果@MethodSource注解的属性值为空,那么默认将会搜索与当前单元测试方法名字一致的工厂方法
// TestPojo为自定的一个类
@ParameterizedTest
@MethodSource("methodSourceTestFactory")
public void parameterizedMethodSourceTest(TestPojo testPojo){
System.out.println(testPojo.getName());
}
public static Stream<TestPojo> methodSourceTestFactory(){
TestPojo testPojo = new TestPojo("zsl",23);
Stream<TestPojo> testPojo1 = Stream.of(testPojo);
return testPojo1;
}
测试方法需要传入多个参数,前面无论是@ValueSource、@MethodSource还是@EnumSource都无法一次调用传入多个参数。所以Junit提供@CsvSource注解完成该功能,这个注解也可以理解为将参数进行拆分,所以会涉及到内容以及分隔符两个属性
序列号 | 属性名 | 属性作用 | 默认值 |
---|---|---|---|
1 | value | 参数值数组 | “” |
2 | delimiter | 分隔符号 | , |
@ParameterizedTest
@CsvSource (value = {"1|2","3|4"},delimiter = '|')
public void parameterizedCvsSourceTest(String fruit, int rank) {
System.out.println(fruit);
System.out.println(rank);
}
某些场景下参数内包含分隔符,但是其内容又不允许被分隔。这时候就需要使用''
单引号将其包裹,这样就不会被分隔符分隔
@ParameterizedTest
@CsvSource (value = {"1,2","3,'4,5'"})
public void parameterizedCvsSourceTest(String fruit, String rank) {
System.out.println(fruit);
System.out.println(rank);
}
如果参数数量过多,单元测试方法上书写影响单元测试类阅读性,则可以使用注解@CsvFileSouce读取一个文件作为数据源。当然文件的内容与上述规则一致,需要注意的就一点,引号字符需要使用""
双引号确认,而不是上述的单引号
@ParameterizedTest
@CsvFileSource(resources = {"CsvSource.csv"})
public void parameterizedCsvFileSourceTest(int n1,int n2){
System.out.println(n1);
System.out.println(n2);
}