AssertJ 教程
本文學習AssertJ,一個開源的、社區驅動的測試庫,可以寫流暢的、豐富的Java測試斷言,我們主要聚焦AssertJ-core提供的功能。
1. 概述
1.1. 依賴
首先需要增加相應依賴,Spring Boot默認已經加載。
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.4.1</version>
<scope>test</scope>
</dependency>
該依賴僅包括基本的java斷言,包括Java 8特性,如果需要使用高級斷言,需要單獨增加額外的模塊。對於Java7及以前版本需要使用2.x.x版本。讀者可以選擇合適版本或最新版本。
1.2. 簡介
AssertJ提供一組類和工具方法,可以很容易寫出流暢、優美的斷言方法:
- Standard Java
- Java 8
- Guava
- Joda Time
- Neo4J and
- Swing components
讀者可以在其官網上查看所有有效模塊。下面是從官網摘取的幾個簡單示例看看:
assertThat(frodo)
.isNotEqualTo(sauron)
.isIn(fellowshipOfTheRing);
assertThat(frodo.getName())
.startsWith("Fro")
.endsWith("do")
.isEqualToIgnoringCase("frodo");
assertThat(fellowshipOfTheRing)
.hasSize(9)
.contains(frodo, sam)
.doesNotContain(sauron);
上面示例僅爲冰山一角,但可以讓我們瞭解下AssertJ寫斷言的大致情況。
2. 實戰學習
本節我們將集中於學習AssertJ並探索其可能性。引入相應依賴或jar包之後,應用僅需在測試類中增加一句靜態導入語句:
import static org.assertj.core.api.Assertions.*;
2.1. 寫斷言
寫斷言首先需要傳入測試對象至Assertions.assertThat()
方法,然後跟上實際的斷言方法。與其他庫不同,下面代碼沒有實際斷言任何內容,也永遠不會產生失敗的測試:
assertThat(anyRefenceOrValue);
如果利用IDE代碼提示特性,寫AssertJ斷言將變得難以置信地容易,所有方法都是自描述的,下面截圖來着IDEA:
我們看到有很多與字符串相關方法可以選擇,下面看看這些API的詳細應用。
2.2. 對象斷言
對象可以使用多種方式進行比較,既可以兩個對象進行比較也可以對象的字段進行比較。下面示例看Dog類的對象fido和fidosClone之間比較:
public class Dog {
private String name;
private Float weight;
// standard getters and setters
}
Dog fido = new Dog("Fido", 5.25);
Dog fidosClone = new Dog("Fido", 5.25);
也可以使用下面斷言進行比較:
assertThat(fido).isEqualTo(fidosClone);
該對象引用之間比較會失敗。如果比較其內容,可以使用isEqualToComparingFieldByFieldRecursively()
方法:
assertThat(fido).isEqualToComparingFieldByFieldRecursively(fidosClone);
當對兩個對象fido和fidosClone進行按字段遞歸比較,兩者是相等。有許多斷言方法提供不同方式進行比較,還可以對其字段進行檢查和斷言。
2.3. 布爾比較
布爾比較函數:
- isTrue()
- isFalse()
示例如下:
assertThat("".isEmpty()).isTrue();
2.4. Iterable/Array斷言
對於Iterable/Array有多種斷言方法判斷其內容是否存在。最常見的是判斷是否存在給定元素:
List<String> list = Arrays.asList("1", "2", "3");
assertThat(list).contains("1");
或判斷是否爲空:
assertThat(list).isNotEmpty();
或如果List已給定元素開頭:
assertThat(list).startsWith("1");
如果在一個對象上進行多個斷言,可以很容易採用鏈接方式。下面示例首先檢查列表是否爲空,然後判斷是否包括“1”元素,不包括空值,並且包括元素序列“2”、“3”:
assertThat(list)
.isNotEmpty()
.contains("1")
.doesNotContainNull()
.containsSequence("2", "3");
該類型還有很多其他可能的斷言,讀者可以自己查看官網文檔。
2.5. 字符斷言
字符類型斷言一般涉及比較和檢查字符是否來自Unicode表。請看實例:
assertThat(someCharacter)
.isNotEqualTo('a')
.inUnicode()
.isGreaterThanOrEqualTo('b')
.isLowerCase();
方法幾乎都是自描述,不再解釋。
2.7. 類斷言
類斷言一般檢查其字段和類的類型,註解是否存在、是否爲final類。如果判斷Runnable類是否爲接口:
assertThat(Runnable.class).isInterface();
或者判斷一個類是否從另一個類賦值:
assertThat(Exception.class).isAssignableFrom(NoSuchElementException.class);
2.7. 文件斷言
File斷言檢查文件實例是否存在,是目錄或文件,有一定內容,是否可讀,具有特定擴展名。
下面示例執行一些列檢查:
assertThat(someFile)
.exists()
.isFile()
.canRead()
.canWrite();
2.8. 數值類型斷言
數值類型包括Double/Float/Integer及其他類型。斷言主要比較數值在一定偏移量之內或之外。舉例,檢查兩個數值在一定精度範圍內是否相等:
assertThat(5.1).isEqualTo(5, withPrecision(1d));
注意這裏使用withPrecision(Double offset) 方法生成偏移量對象。
2.9. InputStream斷言
流斷言只有一個方法:
hasSameContentAs(InputStream expected),示例如下:
assertThat(given).hasSameContentAs(expected);
2.10. Map斷言
Map斷言主要檢查map是否包括特定項(key,value對),或key和value單獨比較。示例如下:
assertThat(map)
.isNotEmpty()
.containsKey(2)
.doesNotContainKeys(10)
.contains(entry(2, "a"));
2.11. Throwable斷言
Throwable斷言主要檢查異常消息,棧跟蹤,原因(cause)檢查或驗證。示例如下:
assertThat(ex).hasNoCause().hasMessageEndingWith("c");
3. 斷言描述
爲了更好描述斷言,可以在斷言中動態生成自定義描述,使用as方法,示例如下:
assertThat(person.getAge())
.as("%s's age should be equal to 100", person.getName())
.isEqualTo(100);
運行測試輸出結果如下:
[tom's age should be equal to 100] expected:<100> but was:<27>
4. 總結
本文簡要說明了AssertJ提供的各種斷言方法,幫助我們更便捷地寫各種測試斷言,更多功能可參考官網。