Junit5系列-Junit5中Assertions斷言類
系列導航
簡介
junit5中的JUnit Jupiter提供了Assertions類來替代了junit4中的Assert類並且新增了一些新的方法,所以工作過程中完全可以使用Assertions代替Assert類。
其包名稱為:org.junit.jupiter.api.Assertions
Assertions中提供的方法都是靜態方法,我們可以通過import靜態資源進行使用,例如:
import static org.junit.jupiter.api.Assertions.*;
當然上述是匯入了所有的方法,單獨匯入也可。
案例解析
下面對Assertions進行一個簡單的應用
程式碼的註釋都很清楚,就不再多說了
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static java.time.Duration.ofMillis;
import static java.time.Duration.ofMinutes;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author liyangyang
* @date 2019/1/8
*/
class AssertionsDemo {
//定義一個person物件,Person類裡面有兩個引數lastName,firstName
static Person person = new Person();
/**
* 使用 @BeforeAll註解在所有測試方法執行前執行person物件的賦值
*/
@BeforeAll
static void initPerson(){
person.setFirstName("John");
person.setLastName("Doe");
}
/**
* assertEquals比較兩個值是否相同
* assertTrue 判斷括號裡面的引數是否為true
*/
@Test
void standardAssertions() {
assertEquals(2, 2);
//當不相等時,會列印出第三個引數,下面的所有的此型別的引數都是這種作用
assertEquals(4, 5, "The optional assertion message is now the last parameter.");
assertTrue('a' < 'b', "Assertion messages can be lazily evaluated -- "
+ "to avoid constructing complex messages unnecessarily.");
}
/**
* assertAll()方法用於將多個測試語句放在一個組中執行
* 組中若有一個測試語句不通過,則這個組將會一起報錯.
* 方法中第一個引數:組名稱
* 方法中第二個引數:組測試語句
*/
@Test
void groupedAssertions() {
assertAll("person",
() -> assertEquals("John", person.getFirstName()),
() -> assertEquals("Doe", person.getLastName())
);
}
/**
* assertAll()方法也可以巢狀多個assertAll()方法
* 其中巢狀的多個測試組,這些組只會列印出這個組和父組的錯誤,對其他的組沒有影響
*/
@Test
void dependentAssertions() {
assertAll("properties",
//第一個測試組
() -> {
String firstName = person.getFirstName();
assertNotNull(firstName);
assertAll("first name",
() -> assertTrue(firstName.startsWith("J")),
() -> assertTrue(firstName.endsWith("n"))
);
},
//第二個測試組
() -> {
String lastName = person.getLastName();
assertNotNull(lastName);
assertAll("last name",
() -> assertTrue(lastName.startsWith("D")),
() -> assertTrue(lastName.endsWith("e"))
);
}
);
}
/**
* assertThrows()可以用來判斷lambda表示式中的程式碼丟擲的異常
* 比如下面案例就是測試了丟擲異常的資訊是否相同
* 引數:
* 1:異常類宣告
* 2:測試程式碼Lambda表示式
*/
@Test
void exceptionTesting() {
Throwable exception = assertThrows(IllegalArgumentException.class, () -> {
try {
//這裡只是簡單的做個測試,當然1/0不該拋IllegalArgumentException異常 ,只是簡單的測試一下
int s = 1/0;
}catch (Exception e){
throw new IllegalArgumentException("a message");
}
});
assertEquals("a message", exception.getMessage());
}
/**
* assertTimeout()對方法執行時間進行測試
* 這裡要藉助java.time.Duration中的方法結合實現
* 例項中執行的程式碼部分必須在2分鐘之內執行完畢,否則測試不通過
*/
@Test
void timeoutNotExceeded() {
assertTimeout(ofMinutes(2), () -> {
//執行的程式碼部分
});
}
/**
* assertTimeout()還可以接受一個返回值(泛型 T)
* 被測試程式碼如果通過測試並返回一個值,這個值被assertTimeout()方法返回
*/
@Test
void timeoutNotExceededWithResult() {
String actualResult = assertTimeout(ofMinutes(2), () -> {
return "a result";
});
assertEquals("a result", actualResult);
}
/**
* assertTimeout()毫秒案例
*/
@Test
void timeoutExceeded() {
assertTimeout(ofMillis(10), () -> {
Thread.sleep(100);
});
}
}
這裡只是介紹一下其用法,其中還有好多方法沒涉及到,者要等我們在使用的過程中再去查詢合適的方法。
相信通過上述案例你應該對Assertions有個大體的瞭解, 下面再細說一下。
原始碼解析
因為程式碼太長了,就不貼程式碼了,大家有需要可以自行檢視。
裡面有好多靜態測試方法,每個方法又有各自的過載。
這只是擷取了不到三分之一的方法。
下面通過介紹public static void assertNull(Object actual, String message)
這個判斷物件為空的方法,來大致的看一下其實現過程。
- Assertions中的assertNull方法原始碼
public static void assertNull(Object actual, String message) {
AssertNull.assertNull(actual, message);
}
呼叫了AssertNull類中的assertNull方法
- AssertNull類中的assertNull方法原始碼
static void assertNull(Object actual, String message) {
if (actual != null) {
failNotNull(actual, message);
}
}
- 判斷引數actual是否為null,若為null則表示測試成功,方法結束,不報錯。
- 如果引數actual不為空,則要呼叫failNotNull方法
- failNotNull方法原始碼
private static void failNotNull(Object actual, String message) {
AssertionUtils.fail(AssertionUtils.buildPrefix(message) + "expected: <null> but was: <" + actual + ">", (Object)null, actual);
}
這個方法主要就是組裝了錯誤訊息,並將被驗證引數傳遞到下一層
- fail方法原始碼
static void fail(String message, Object expected, Object actual) {
throw new AssertionFailedError(message, expected, actual);
}
在這裡直接丟擲了一個自定義異常。
到這裡一個測試的過程就幾乎結束了,大體來說不難,大家如果還想了解其他的方法原始碼,可以自己debug跟蹤原始碼來檢視。
- 最後簡單的看一下這個自定義異常AssertionFailedError吧
其繼承關係為:
public class AssertionFailedError extends AssertionError
--->
public class AssertionError extends Error
--->
public class Error extends Throwable
可以看書這是正常的自定義異常的模式,繼承JDK自帶的java.long.error類,實現自己的Error類,這裡的AssertionError是所有Assertions類中方法報錯的父類,其他特定的錯誤類就是繼承的此類。
Assertions與AssertNull
另外,在上述過程中我們知道,Assertions.assertNull()其實就是呼叫的AssertNull中的assertNull()實現的,我們看一下AssertNull的原始碼:
class AssertNull {
private AssertNull() {
}
//包可見靜態方法
static void assertNull(Object actual) {
assertNull(actual, (String)null);
}
//包可見靜態方法
static void assertNull(Object actual, String message) {
if (actual != null) {
failNotNull(actual, message);
}
}
//包可見靜態方法
static void assertNull(Object actual, Supplier<String> messageSupplier) {
if (actual != null) {
failNotNull(actual, AssertionUtils.nullSafeGet(messageSupplier));
}
}
//類內呼叫方法
private static void failNotNull(Object actual, String message) {
AssertionUtils.fail(AssertionUtils.buildPrefix(message) + "expected: <null> but was: <" + actual + ">", (Object)null, actual);
}
}
再看一下這兩個類是不是在一個包中:
從原始碼和圖片中不難發現,AssertNull中其實和Assertions一樣也是提供了包內可見的靜態方法 ,所以我們也可以通過引入import static org.junit.jupiter.api.AssertNull.*;
來直接使用AssertNull中的方法,不過這可不是個好想法。
Assertions將測試方法集中在該方法內,不僅便於管理,還減少程式碼的複雜度,效能沒有任何影響,為什麼要去直接使用AssertNull等類
呢,嘿嘿
最後:當然,Assertions提供的斷言方法雖然多,但有時候還是不夠的,當Junit5不支援你的單元測試需求時,Junit5官方還是鼓勵程式設計師去使用第三方支援庫的,比如:AssertJ、Hamcrest,Truth等。。。。
如果轉載此博文,請附上本文連結:https://blog.csdn.net/csdn___lyy ,謝謝合作~
如果感覺這篇文章對您有所幫助,請點選一下“喜歡”或者“關注”博主,您的喜歡和關注將是我前進的最大動力!
refer: 官網
我的部落格即將同步至騰訊雲+社群,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=2gwn5c4zib6s0
相關文章
- JUnit5學習之三:Assertions類
- Junit5系列-Junit5中Assumptions假設類
- Junit5系列-Junit5中@Disabled禁止執行
- Junit5系列-Junit5中@DisplayName自定義名稱
- Junit5系列-什麼是Junit5?
- Junit5系列-Junit5中assertThrows()與assertDoesNotThrow()方法詳解
- Junit5系列-Junit5中DisabledCondition條件測試執行
- JUnit5學習之二:Assumptions類
- JUnit5註解學習指引
- JUnit5編寫基本測試
- junit5 是不是全方面吊打 testng
- JUnit5的Tag、Filter、Order、LifecycleFilter
- JUnit5學習之一:基本操作
- JUnit5依賴注入與測試介面依賴注入
- 基於 junit5 實現 junitperf 原始碼分析原始碼
- JUnit5學習之四:按條件執行
- JUnit5學習之八:綜合進階(終篇)
- Java新一代單元測試框架JUnit5速覽Java框架
- JUnit5學習之五:標籤(Tag)和自定義註解
- Springboot整合JUnit5優雅進行單元測試Spring Boot
- Spring 對 Junit4,Junit5 的支援上的運用Spring
- Go 語言關於 Type Assertions 的 坑Go
- JUnit5的條件測試、巢狀測試、重複測試巢狀
- JUnit5學習之六:引數化測試(Parameterized Tests)基礎Zed
- JUnit5學習之七:引數化測試(Parameterized Tests)進階Zed
- 匯出類介面如何斷言
- Java中的斷言assertJava
- Python中斷言assertPython
- 十二、Jmeter 斷言-響應斷言、Json 斷言和 Beanshell 斷言JMeterJSONBean
- 組合語言--單步中斷組合語言
- Python 中何時使用斷言?Python
- Python中何時使用斷言Python
- 測試平臺系列(70) 豐富斷言型別型別
- junit 測試中各種斷言用法
- JavaScript中不得不說的斷言?JavaScript
- 肯定賦值斷言與非空斷言賦值
- 斷言操作
- c#中判斷類是否繼承於泛型基類C#繼承泛型