一:摘要概述
本系列文章將學習使用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>
三:聲明註解@ParameterizedTest
@Test聲明方法爲單元測試方法,如果單元測試方法需要通過執行多次不同參數達到某種測驗效果則需要使用@ParameterizedTest註解。意思就是這個註解相當於參數單元測試的元註解,當然,如果想順利進行參數單元測試,還需要系列參數來源支撐
四:基礎類型來源@ValueSource
將@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);
}
五:空值來源@NullSource @EmptySource
邊界值測試中很重要的一項就是非空測試,校驗空值情況下程序是否可以正常運行不拋出異常。直白點就是檢驗接口是否入參空值做處理,Junit5中提供註解@NullSource與@EmptySource支撐該操作
5.1 支持類型
- NullSource:不支持八種基礎類型,因爲它們沒有null的概念
- EmptySource:List、Set、Map、String以及數組對象等,注意不支持它們的子類,如ArrayList
5.2 效果測試
@ParameterizedTest
@NullSource
@EmptySource
public void parameterizedNullAndEmptySourceTest(String nullSource){
System.out.println(nullSource.length());
}
5.3 註解合併@NullAndEmptySource
Junit5中提供該註解作爲@NullSource與@EmptySource註解的合集,也就是同時具備這倆註解效果
六:枚舉來源@EnumSource
參數對象若爲枚舉對象,則可以使用註解@EnumSource完成測試。該註解將默認調用枚舉類中所有實例進行測試,但是也有相應的參數進行限制
6.1 註解屬性
序列 | 屬性名 | 屬性說明 |
---|---|---|
1 | value | 本次入參枚舉類class對象 |
2 | names | 本次入參枚舉類中實例對象名稱 |
3 | mod | INCLUDE、EXCLUDE限制names屬性值爲包含列舉對象還是祛除names列舉對象,MATCH_ALL、MATCH_ANY則是解析names屬性中的正則表達式匹配枚舉類所有實例的名稱 |
6.2 mod說明
序列 | 屬性值 | 屬性值說明 |
---|---|---|
1 | INCLUDE | 默認屬性值,表示包含names屬性值列舉對象 |
2 | EXCLUDE | 表示祛除names屬性值列舉對象 |
3 | MATCH_ALL | 符合所有names屬性列舉正則規則的枚舉實例 |
4 | MATCH_ANY | 符合一個names屬性列舉正則規則即可的枚舉實例 |
6.3 測試實踐
@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);
}
七:工廠來源@MethodSource
工廠類返回一個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;
}
八:多參數來源@CsvSource
測試方法需要傳入多個參數,前面無論是@ValueSource、@MethodSource還是@EnumSource都無法一次調用傳入多個參數。所以Junit提供@CsvSource註解完成該功能,這個註解也可以理解爲將參數進行拆分,所以會涉及到內容以及分隔符兩個屬性
8.1 屬性簡介
序列號 | 屬性名 | 屬性作用 | 默認值 |
---|---|---|---|
1 | value | 參數值數組 | “” |
2 | delimiter | 分隔符號 | , |
8.2 測試實踐
@ParameterizedTest
@CsvSource (value = {"1|2","3|4"},delimiter = '|')
public void parameterizedCvsSourceTest(String fruit, int rank) {
System.out.println(fruit);
System.out.println(rank);
}
8.3 引號字符
某些場景下參數內包含分隔符,但是其內容又不允許被分隔。這時候就需要使用''
單引號將其包裹,這樣就不會被分隔符分隔
@ParameterizedTest
@CsvSource (value = {"1,2","3,'4,5'"})
public void parameterizedCvsSourceTest(String fruit, String rank) {
System.out.println(fruit);
System.out.println(rank);
}
8.4 分隔文件
如果參數數量過多,單元測試方法上書寫影響單元測試類閱讀性,則可以使用註解@CsvFileSouce讀取一個文件作爲數據源。當然文件的內容與上述規則一致,需要注意的就一點,引號字符需要使用""
雙引號確認,而不是上述的單引號
@ParameterizedTest
@CsvFileSource(resources = {"CsvSource.csv"})
public void parameterizedCsvFileSourceTest(int n1,int n2){
System.out.println(n1);
System.out.println(n2);
}