在 JUnit 中斷言正規表示式匹配
1. 概述
JUnit 成為許多開發人員對 Java 程式碼執行單元測試的首選。在現實場景中,一種常見的測試需求是驗證給定字串是否符合特定的正規表示式 (regex) 模式。
在本教程中,我們將探索在 JUnit 中斷言正規表示式匹配的幾種方法,使我們能夠有效地測試字串模式。
2.問題介紹
問題非常簡單:我們需要一種自然而有效的方法來確認輸入字串與特定的正規表示式模式對齊。理想情況下,我們還應該有一個可靠的方法來斷言相反的情況,即輸入字串與正規表示式模式不符。
讓我們先探索廣泛使用的 JUnit 5 框架,並了解如何使用其標準功能對正規表示式模式比對執行斷言。此外,我們將討論使用 JUnit 5 進行此類斷言時的潛在陷阱。
除了 JUnit 5 之外,還有與 JUnit 5 無縫整合的方便且補充的測試和斷言庫。在本教程中,我們將重點放在其中兩個流行的外部庫。我們將研究如何在這些庫的上下文中斷言正則表達式模式匹配,從而擴展我們的工具包以進行高效測試。
3. 使用標準 JUnit 5 方法
JUnit 5 在org.junit.jupiter.api.Assertions
套件中提供了一系列常用的斷言,例如assertSame(), assertEquals(),
等。
然而,JUnit 5 缺乏用於正規表示式模式驗證的專用斷言方法,例如「 assertMatches()
」。由於String.matches()
方法傳回一個boolean
,我們可以使用assertTrue()
方法來確保字串與正規表示式模式相符:
assertTrue("Java at Baeldung".matches(".* at Baeldung$"));
毫不奇怪,如果我們想斷言字串與正規表示式模式不匹配,我們可以使用assertFalse()
斷言:
assertFalse("something else".matches(".* at Baeldung$"));
4. 為什麼我們不應該使用assertLinesMatch()
方法進行正規表示式匹配測試
雖然我們之前提到 JUnit 5 缺乏專用的正規表示式模式斷言方法,但有些人可能不同意這一說法。 JUnit 5確實提供了assertLinesMatch()
方法,它可以驗證文字行內的正規表示式模式匹配,例如:
assertLinesMatch(List.of(".* at Baeldung$"), List.of("Kotlin at Baeldung"));
如上面的範例所示,由於該方法接受兩個字串列表(預期列表和實際列表),因此我們將正則表達式模式和輸入字串包裝在列表中,並且測試通過。
但是,值得注意的是,使用assertLinesMatch()
方法測試正規表示式匹配並不安全。一個例子可以快速展示它:
assertFalse(".* at Baeldung$".matches(".* at Baeldung$"));
assertLinesMatch(List.of(".* at Baeldung$"), List.of(".* at Baeldung$"));
在上面的範例中,我們的輸入字串和正規表示式模式是相同的:「 .* at Baeldung$
」。顯然,輸入與模式不匹配,因為輸入字串以“ $
”字元而不是“ Baeldung
”結尾。因此, assertFalse()
斷言通過。
然後,我們將相同的輸入和正規表示式模式傳遞給assertLinesMatch()
方法,斷言已經通過了!這是因為assertLinesMatch()
透過三個步驟驗證預期清單和實際清單中的每一對:
- 如果預期字串等於實際字串,則繼續下一對
- 否則,將預期字串視為正規表示式模式並檢查
actualString.matches(expectedString).
如果結果為true,
則繼續下一對 - 否則,如果預期字串是快轉標記,則相應地套用快轉實際行並從第一步開始
我們不會深入探討assertLinesMatches()
方法的用法。如上面的步驟所示,正規表示式模式測試在步驟 2 中執行。在我們的範例中,作為輸入的實際字串和預期字串(正規表示式模式)是 equal 的。因此,步驟1通過了。也就是說,斷言在沒有應用正規表示式匹配檢查的情況下就通過了。
因此, assertLinesMatch()
方法不是驗證正規表示式模式匹配的正確斷言方法。
5.使用AssertJ的matches()
方法
借助流行的 AssertJ 庫,我們可以快速編寫流暢的斷言。 AssertJ 提供matches()
方法來測試正規表示式模式:
// assertThat() below is imported from org.assertj.core.api.Assertions
assertThat("Linux at Baeldung").matches(".* at Baeldung$");
顧名思義, doesNotMatch()
方法允許我們執行否定測試場景:
assertThat("something unrelated").doesNotMatch(".* at Baeldung$");
6. 使用 Hamcrest 的matchesPattern()
方法
同樣,Hamcrest 是另一個廣泛使用的測試框架。此外,它還提供matchesPattern()
方法用於正規表示式匹配測試:
// assertThat() below is imported from org.hamcrest.MatcherAssert
assertThat("Computer science at Baeldung", matchesPattern(".* at Baeldung$"));
要執行負正規表示式比對測試,我們可以使用not()
來否定matchesPattern()
所建立的Matcher
:
assertThat("something unrelated", not(matchesPattern(".* at Baeldung$")));
七、結論
在本文中,我們探索了斷言正規表示式模式匹配的不同方法。
兩個常用的函式庫 AssertJ 和 Hamcrest 提供專用的正規表示式匹配測試方法。另一方面,如果我們希望最大限度地減少外部依賴,JUnit 5 的assertTrue()
與String.matches()
方法結合也可以實現相同的目標。
此外,我們也討論了不應使用 JUnit 5 的assertLinesMatch()
進行正規表示式模式比對測試。
與往常一樣,範例的完整原始程式碼可在 GitHub 上取得。