JUnit5官方文档:JUnit 5 User Guide
JUnit是Java中的一个单元测试框架,开发人员可以通过编写代码的方式来进行自动化的测试,当测试的用例比较多,或者经常需要回归性的测试的时候,编写代码的方式就显得非常必要了~
在JUnit中编写代码主要是通过注解来标识代码,以及使用断言的方式来验证程序的结果是否与预期结果相符。
要想使用JUnit,我们需要引入相关依赖。
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.1</version>
</dependency>
一、基本测试
1.1 单个测试
在JUnit中,要想标识一个测试用例,可以使用@Test注解
public class JUnit {
@Test
public void test01(){
System.out.println("这是test01方法");
}
}
点击左侧按钮即可对本测试方法进行测试
1.2 多个测试
当我们的测试方法很多的时候,如何去管理呢?
可能一些测试的方法依赖与另一个测试的方法,即需要规定测试的顺序;
又或者对于每一次执行测试方法,需要做一些相同的前置工作,即需要对每个测试方法进行战前准备与善后工作.
注解:
注解 | 功能 |
@TestMethodOrder | 写在类上,可以根据指定的方式进行自定义顺序执行 |
@BeforeEach | 在每个测试方法前执行 |
@AfterEach | 在每个测试方法后执行 |
@BeforeAll | 在所有测试方法前执行 |
@AfterAll | 在所有测试方法后执行 |
@TestMethodOrder
在@TestMethodOrder中,主要通过两种方式来标识执行顺序:按照方法的字典序顺序执行,或者通过@Order注解手动标识
@TestMethodOrder(MethodOrderer.MethodName.class)
public class JUnit {
@Test
public void test01(){}
}
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class JUnit02{
@Test
@Order(2)
public void test01(){}
@Test
@Order(1)
public void test02(){}
}
所有可配置的顺序:
@BeforeEach和@AfterEach
public class JUnit {
@BeforeEach
public void beforeEach(){
System.out.println("beforeEach执行");
}
@AfterEach
public void afterEach(){
System.out.println("afterEach执行");
}
}
@BeforeAll和@AfterAll也是同理的~不同的是修饰的方法必须为static修饰过的。
1.3 断言
断言的使用是为了解决测试用例太多,不方便去观察测试结果而使用的。
如果通过观察日志的方式不是不行,太很费时间,当然也可以通过抛出异常,但比较麻烦,因此使用断言的方式更加优雅。
断言中的方法都在Assertions类下。
方法 | 功能 |
assertArrayEquals | 判断两个数组是否相同 |
assertEquals | 判断两个值石是否相同 |
assertNotEquals | 判断两个值是否不同 |
assertNull | 判断是否为空 |
assertNotNull | 判断是否不为空 |
assertTrue | 判断是否为true |
assertFalse | 判断是否为false |
public class JUnit {
@Test
public void test01(){
int sum = 1 + 1;
Assertions.assertEquals(sum, 2);
}
}
二、参数化测试
如果我们的测试方法需要参数传递,而不想要通过另一个方法来调用当前这个测试方法的时候,即降低测试方法间的耦合程度,该如何给参数赋值呢?
对于每个需要进行参数化测试的方法,加的注解不再是@Test而是@ParameterizedTest
这就需要用到参数化测试了。需要引入如下依赖:
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.9.1</version>
</dependency>
2.1 单个参数
单个参数指的是方法中只需要传递一个参数的情况,使用的注解是@ValueSource
传统方式,通过另一个方法区传递参数值,进行调用。
使用@ValueSource
public class JUnit {
@ParameterizedTest
@ValueSource(strings = {"zhangsan", "lisi", "wangwu"})
//每次只传递一个参数,一共传递三次
public void test01(String str){
System.out.println(str);
}
}
2.2 多个参数
多个参数指的是方法中传递多个参数的情况,使用的注解是@CsvSource
public class JUnit {
@ParameterizedTest
@CsvSource({"'1', 'zhangsan'", "'2', 'lisi'"})
public void test01(int id, String name){
System.out.println("id:" + id + " " + "name:" + name);
}
}
2.3 从文件读取参数
官方规定使用是csv文件,可以从类路径读取也可以从本地文件进行读取。
读取的时候会扫描每一行,并可以指定跳过扫描的行数。
如果要从类路径中读取的话,需要将下述代码中的files改为resources,下述代码是从本地文件读取的。
public class JUnit {
@ParameterizedTest
@CsvFileSource(files = "./data.csv", numLinesToSkip = 1)
public void test01(int id, String name){
System.out.println("id:" + id + " " + "name:" + name);
}
}
此处的numLinuesToSkip表示的是跳过文件的第一行.
data.csv
id, name
1, zhangsan
2, lisi
3, wangwu
三、套件测试
上述都是从方法的维度进行的测试管理的。
当然我们还可以从类和包的维度进行管理。
引入依赖:
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>1.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>
@Suite 表示当前类是一个测试套件
如何去指定执行测试的类、包呢?
使用@SelectClasses和@SelectctPackets
@Suite
@SelectClasses({ClassOneUnitTest.class, ClassTwoUnitTest.class})
public class JUnitSelectClassesSuite {
}
@Suite
@SelectPackages({"com.baeldung.testsuite", "com.baeldung.testsuitetwo"})
public class JUnitSelectPackagesSuite {
}
当然我们也可以指定执行类/包中的方法或者不执行。
使用的注解是:
@Includexxx 和 @Excludexxx
使用@Includexxx表示仅执行里面被包括的方法,忽略其他
使用@Excludexxx表示不执行里面的方法。