1. 概述
在本文中,我們將探索 JsonUnit 庫並利用它創建 JSON 對象的可表達斷言。我們首先將從一個簡單的示例開始,展示 JsonUnit 與 AssertJ 之間的無縫集成。
之後,我們將學習如何驗證 JSON 與模板化的 String。 這種方法提供靈活性,並允許我們使用自定義佔位符來將元素值與各種標準或完全忽略特定的 JSON 路徑進行匹配。
2. 入門
JsonUnit 項目包含幾個可以獨立導入的模塊。<em ><a href="https://mvnrepository.com/artifact/net.javacrumbs.json-unit/json-unit-assertj">json-unit-assertj</a></em> 模塊是推薦使用的方式,它提供了一個流暢的 API 以及與 AssertJ 庫的無縫集成。
讓我們將此依賴項添加到我們的 <em >pom.xml</em> 中:
<dependency>
<groupId>net.javacrumbs.json-unit</groupId>
<artifactId>json-unit-assertj</artifactId>
<version>3.5.0</version>
<scope>test</scope>
</dependency>該庫假設已經存在於 classpath 中,並且會自動嘗試使用 JSON 解析器。目前支持的集成包括 Gson、org.json、Moshi 和 Jackson2。
現在,我們可以使用靜態工廠方法 assertThatJson() 創建斷言對象。 因此,我們將能夠使用 JsonUnit 的流暢 API 來驗證測試的 JSON 是否是一個有效的 JSON 對象,並驗證其鍵值對:
@Test
void whenWeVerifyAJsonObject_thenItContainsKeyValueEntries() {
String articleJson = """
{
"name": "A Guide to Spring Boot",
"tags": ["java", "spring boot", "backend"]
}
""";
assertThatJson(articleJson)
.isObject()
.containsEntry("name", "A Guide to Spring Boot")
.containsEntry("tags", List.of("java", "spring boot", "backend"));
}JsonUnit 允許我們輕鬆地瀏覽 JSON 對象,同時利用 AssertJ 的強大斷言功能進行驗證。例如,我們可以使用諸如 node() 方法之類的手段來瀏覽 JSON,以及 isArray() 方法來訪問專門為斷言集合而設計的 API:
assertThatJson(articleJson)
.isObject()
.containsEntry("name", "A Guide to Spring Boot")
.node("tags")
.isArray()
.containsExactlyInAnyOrder("java", "spring boot", "backend");另一方面,我們可以以聲明式的方式將測試對象與一個簡單的 JSON 字符串進行比較。
要做到這一點,我們只需要將預期內容包裹在 ExpectedNode 實例中,可以使用函數 JsonAssertion.json():
assertThatJson(articleJson)
.isObject()
.isEqualTo(json("""
{
"name": "A Guide to Spring Boot",
"tags": ["java", "spring boot", "backend"]
}
"""));3. 支持的功能
該庫提供了 多種功能,例如導航複雜的 JSON 路徑、忽略字段或值,以及斷言自定義匹配器或正則表達式模式。雖然我們不會詳細討論所有功能,但我們將探索一些關鍵功能。
3.1. 選項
JsonUnit 允許我們為每個斷言定義各種配置。我們可以通過 Option 枚舉中找到支持的功能,並通過 when() 方法啓用它們。
以下是如何啓用 IGNORE_ARRAY_ORDER 和 IGNORE_EXTRA_ARRAY_ITEMS 選項,以一種驗證 JSON 包含 tags “java” 和 “backend” 的任何順序的方式:
assertThatJson(articleJson)
.when(Option.IGNORING_ARRAY_ORDER)
.when(Option.IGNORING_EXTRA_ARRAY_ITEMS)
.node("tags")
.isEqualTo(json("""
["backend", "java"]
"""));3.2. 佔位符
在驗證 JSON 輸出與預期內容是否匹配時,該庫允許將預期結果進行模板化。 例如,佔位符如 ${json-unit.any-string} 和 ${json-unit.ignore-element} 可以驗證文章的 名稱 作為字符串,同時忽略其 標籤 列表:
assertThatJson(articleJson)
.isEqualTo(json("""
{
"name": "${json-unit.any-string}",
"tags": "${json-unit.ignore-element}"
}
"""));同樣,我們還可以使用佔位符,例如 ${json-unit.any-number}、${json-unit.any-boolean}、${json-unit.regex},甚至可以根據特定用例創建自定義佔位符。
3.3. 忽略路徑
我們已經學習瞭如何使用佔位符來忽略 JSON 對象中的元素。 但是,我們還可以利用 whenIgnoringPaths() 方法來定義在執行斷言時應忽略的 JSON 路徑:
assertThatJson(articleJson)
.whenIgnoringPaths("tags")
.isEqualTo(json("""
{
"name": "A Guide to Spring Boot",
"tags": [ "ignored", "tags" ]
}
"""));
}如我們所見,當使用 whenIgnoringPaths(“tags”) 時,即使兩個 JSON 對象對於 tags 鍵的值不同,斷言仍然通過。
4. 結論
在本實踐教程中,我們探討了 JsonUnit 的基本原理,並探索了其 API,用於創建流暢且聲明式的斷言,從而使 JSON 驗證變得簡單而富有表現力。
我們還學習瞭如何通過將 JSON 內容與模板化的 String 進行比較來驗證 JSON 內容。 這種技術在與諸如配置 Option、自定義佔位符和類型匹配器等其他庫功能結合使用時尤其強大。