知識庫 / Testing RSS 訂閱

JSONassert 入門

JSON,Testing
HongKong
5
09:56 PM · Dec 05 ,2025

1. 概述

本文將介紹 JSONAssert 庫 – 該庫專注於理解 JSON 數據以及使用該數據編寫複雜的 JUnit 測試。

2. Maven 依賴

首先,讓我們添加 Maven 依賴:

<dependency>
    <groupId>org.skyscreamer</groupId>
    <artifactId>jsonassert</artifactId>
    <version>1.5.0</version>
</dependency>

請查看最新版本的庫,這裏

3. Working With Simple JSON Data

3.1. 使用寬鬆模式 (Lenient Mode)

讓我們用一個簡單的 JSON 字符串比較開始我們的測試:

String actual = "{id:123, name:\"John\"}";
JSONAssert.assertEquals(
  "{id:123,name:\"John\"}", actual, JSONCompareMode.LENIENT);

測試將通過,因為預期 JSON 字符串與實際 JSON 字符串相同。

比較模式 LENIENT 表示,即使實際 JSON 包含擴展字段,測試仍會通過。

String actual = "{id:123, name:\"John\", zip:\"33025\"}";
JSONAssert.assertEquals(
  "{id:123,name:\"John\"}", actual, JSONCompareMode.LENIENT);

如我們所見,實參變量包含一個額外的字段 zip,而這在預期 String 中不存在。儘管如此,測試仍然會通過。

這個概念在應用程序開發中很有用。這意味着我們的 API 可以增長,返回額外的字段作為需要,而不會破壞現有的測試。

3.2. 使用 嚴格模式

可以使用 嚴格模式來改變上一節中提到的行為:

String actual = "{id:123,name:\"John\"}";
JSONAssert.assertNotEquals(
  "{name:\"John\"}", actual, JSONCompareMode.STRICT);

請注意以上示例中使用了 assertNotEquals()

3.3. 使用布爾值代替 JSONCompareMode

比較模式也可以通過使用一個重載的方法來實現,該方法接受布爾值而不是 JSONCompareMode,並且設置 LENIENT = falseSTRICT = true

String actual = "{id:123,name:\"John\",zip:\"33025\"}";
JSONAssert.assertEquals(
  "{id:123,name:\"John\"}", actual, JSONCompareMode.LENIENT);
JSONAssert.assertEquals(
  "{id:123,name:\"John\"}", actual, false);

actual = "{id:123,name:\"John\"}";
JSONAssert.assertNotEquals(
  "{name:\"John\"}", actual, JSONCompareMode.STRICT);
JSONAssert.assertNotEquals(
  "{name:\"John\"}", actual, true);

3.4. 邏輯比較

正如前面所述,<em >JSONAssert</em> 會對數據進行邏輯比較。這意味着在處理 JSON 對象時,元素的順序不重要:

String result = "{id:1,name:\"John\"}";
JSONAssert.assertEquals(
  "{name:\"John\",id:1}", result, JSONCompareMode.STRICT);
JSONAssert.assertEquals(
  "{name:\"John\",id:1}", result, JSONCompareMode.LENIENT);
<p>嚴格遵守或不遵守,以上測試在兩種情況下都將通過。</p>
<p>通過使用不同類型的值,還可以演示邏輯比較的一個例子:</p>
JSONObject expected = new JSONObject();
JSONObject actual = new JSONObject();
expected.put("id", Integer.valueOf(12345));
actual.put("id", Double.valueOf(12345));

JSONAssert.assertEquals(expected, actual, JSONCompareMode.LENIENT);

首先需要注意的是,我們使用了 JSONObject 而不是像之前示例中那樣使用字符串。 其次,我們使用了 Integer 用於 expected,以及 Double 用於 actual。 測試結果將與類型無關,因為它們都使用了相同的邏輯值 12345。

即使在嵌套對象表示的情況下,這個庫也能很好地工作:

String result = "{id:1,name:\"Juergen\", 
  address:{city:\"Hollywood\", state:\"LA\", zip:91601}}";
JSONAssert.assertEquals("{id:1,name:\"Juergen\", 
  address:{city:\"Hollywood\", state:\"LA\", zip:91601}}", result, false);

3.5. 使用用户自定義消息的斷言

所有 <em>assertEquals()</em><em>assertNotEquals()</em> 方法都接受一個 <em>String</em> 作為第一個參數。這個消息允許我們自定義測試用例,在測試失敗時提供有意義的錯誤信息。

String actual = "{id:123,name:\"John\"}";
String failureMessage = "Only one field is expected: name";
try {
    JSONAssert.assertEquals(failureMessage, 
      "{name:\"John\"}", actual, JSONCompareMode.STRICT);
} catch (AssertionError ae) {
    assertThat(ae.getMessage()).containsIgnoringCase(failureMessage);
}

在任何情況下,如果發生錯誤,整個錯誤信息都會更清晰明瞭:

Only one field is expected: name 
Unexpected: id

第一行是用户指定的提示信息,第二行是庫提供補充的信息。

4. Working With JSON Arrays

The comparison rules for JSON arrays differ a little, compared to JSON objects.

4.1. 數組元素順序

在嚴格比較模式下,數組中的元素順序必須完全一致。然而,在寬鬆比較模式下,元素順序並不重要:

String result = "[Alex, Barbera, Charlie, Xavier]";
JSONAssert.assertEquals(
  "[Charlie, Alex, Xavier, Barbera]", result, JSONCompareMode.LENIENT);
JSONAssert.assertEquals(
  "[Alex, Barbera, Charlie, Xavier]", result, JSONCompareMode.STRICT);
JSONAssert.assertNotEquals(
  "[Charlie, Alex, Xavier, Barbera]", result, JSONCompareMode.STRICT);

在API返回一個排序後的元素數組的場景中,這非常有用,並且我們想要驗證響應是否已排序。

4.2. 數組中的擴展元素

另一個區別在於,在處理 JSON 數組時,不允許使用擴展元素:

擴展元素在處理 JSON 數組時是被禁止的。

String result = "[1,2,3,4,5]";
JSONAssert.assertEquals(
  "[1,2,3,4,5]", result, JSONCompareMode.LENIENT);
JSONAssert.assertNotEquals(
  "[1,2,3]", result, JSONCompareMode.LENIENT);
JSONAssert.assertNotEquals(
  "[1,2,3,4,5,6]", result, JSONCompareMode.LENIENT);

上述示例清楚地表明,即使使用寬鬆比較模式,預期數組中的項目必須與實際數組中的項目完全匹配。添加或刪除,即使單個元素,也會導致失敗。

4.3. 數組特定操作

我們還提供了一些技術,用於進一步驗證數組的內容。

假設我們想要驗證數組的大小。這可以通過使用具體的語法來實現,以期望的值作為驗證標準:

String names = "{names:[Alex, Barbera, Charlie, Xavier]}";
JSONAssert.assertEquals(
  "{names:[4]}", 
  names, 
  new ArraySizeComparator(JSONCompareMode.LENIENT));

String{names:[4]}” 指定了數組的預期大小。

讓我們來看一種其他的比較技術:

String ratings = "{ratings:[3.2,3.5,4.1,5,1]}";
JSONAssert.assertEquals(
  "{ratings:[1,5]}", 
  ratings, 
  new ArraySizeComparator(JSONCompareMode.LENIENT));

上述示例驗證數組中的所有元素必須具有值在 [1, 5] 之間,包括 1 和 5。如果存在任何小於 1 或大於 5 的值,上述測試將會失敗。

5. 進階比較示例

考慮我們的API返回多個id,每個id都是一個Integer值的情況。這意味着所有id都可以使用簡單的正則表達式‘\d’進行驗證。

上述正則表達式可以與CustomComparator結合使用,並應用於所有id的值。如果任何id不匹配正則表達式,則測試將會失敗:

JSONAssert.assertEquals("{entry:{id:x}}", "{entry:{id:1, id:2}}", 
  new CustomComparator(
  JSONCompareMode.STRICT, 
  new Customization("entry.id", 
  new RegularExpressionValueMatcher<Object>("\\d"))));

JSONAssert.assertNotEquals("{entry:{id:x}}", "{entry:{id:1, id:as}}", 
  new CustomComparator(JSONCompareMode.STRICT, 
  new Customization("entry.id", 
  new RegularExpressionValueMatcher<Object>("\\d"))));

上述的“”僅僅是一個佔位符, 可以替換為任何內容。因為它是正則表達式模式 ‘\d‘ 將要應用的地點。由於 本身位於另一個字段 entry 內部,Customization 指定了 的位置,以便 CustomComparator 可以執行比較。

6. 結論

在本文中,我們探討了 JSONAssert 在各種場景中的應用。我們從一個非常簡單的示例開始,然後逐步過渡到更復雜的比較。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.