檢查清單中是否包含具有 Hamcrest 中某些屬性的元素
1. 概述
在使用 Java 編寫單元測試時,尤其是使用 JUnit 框架時,我們經常需要驗證清單中的元素是否具有特定屬性。
Hamcrest 是一個廣泛使用的Matcher
函式庫,它提供了直接且富有表現力的方法來執行這些檢查。
在本教程中,我們將探索如何使用 JUnit 和 Hamcrest 的Matcher
檢查清單是否包含具有特定屬性的元素。
2. 設定 Hamcrest 和範例
在設定範例之前,讓我們快速將 Hamcrest 依賴項新增至pom.xml
:
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
我們可以在 Maven Central 中查看該工件的最新版本。
現在,讓我們建立一個簡單的 POJO 類別:
public class Developer {
private String name;
private int age;
private String os;
private List<String> languages;
public Developer(String name, int age, String os, List<String> languages) {
this.name = name;
this.age = age;
this.os = os;
this.languages = languages;
}
// ... getters are omitted
}
如程式碼所示, Developer
類別擁有一些描述開發人員的屬性,例如開發人員的name
、 age,
作業系統 ( os
) 以及開發人員主要使用的程式語言 ( languages
)。
接下來,讓我們建立Developer
實例的清單:
private static final List<Developer> DEVELOPERS = List.of(
new Developer("Kai", 28, "Linux", List.of("Kotlin", "Python")),
new Developer("Liam", 26, "MacOS", List.of("Java", "C#")),
new Developer("Kevin", 24, "MacOS", List.of("Python", "Go")),
new Developer("Saajan", 22, "MacOS", List.of("Ruby", "Php", "Typescript")),
new Developer("Eric", 27, "Linux", List.of("Java", "C"))
);
我們將以DEVELOPERS
清單為例,介紹如何使用 JUnit 和 Hamcrest 檢查元素是否包含特定屬性。
3. 使用hasItem()
和hasProperty()
Hamcrest 提供了一套豐富、方便的Matcher
。我們可以將hasProperty()
Matcher
與hasItem()
Matcher
結合使用:
assertThat(DEVELOPERS, hasItem(hasProperty("os", equalTo("Linux"))));
此範例示範如何檢查至少一個元素的os
是「 Linux
」。
我們可以將不同的屬性名稱傳遞給hasProperty()
來驗證另一個屬性,例如:
assertThat(DEVELOPERS, hasItem(hasProperty("name", is("Kai"))));
在上面的範例中,我們使用 is() ( **equalTo() ,**
is()
別名)來檢查清單中是否有name
等於“Kai”
的元素。
當然,除了equalTo()
和is()
之外,我們還可以在hasProperty()
中使用其他Matcher
以不同的方式驗證元素的屬性:
assertThat(DEVELOPERS, hasItem(hasProperty("age", lessThan(28))));
assertThat(DEVELOPERS, hasItem(hasProperty("languages", hasItem("Go"))));
斷言語句讀起來就像自然語言,例如:“ assertThat
the DEVELOPERS
list hasItem
which hasProperty
who name isage and value is lessThan 28″
。
anyOf()
和allOf()
匹配器
hasProperty()
可以方便檢查一個屬性。我們也可以透過使用 anyOf() 和[**allOf() .**](https://hamcrest.org/JavaHamcrest/javadoc/2.2/org/hamcrest/Matchers.html#allOf-org.hamcrest.Matcher...-)
anyOf()
多個hasProperty()
呼叫來檢查清單中的元素是否滿足多個屬性。
如果anyOf()
內的任何一個Matcher
被匹配,則整個anyOf()
就滿足。接下來我們透過一個例子來理解:
assertThat(DEVELOPERS, hasItem(
anyOf(
hasProperty("languages", hasItem("C")),
hasProperty("os", is("Windows"))) // <-- No dev has the OS "Windows"
));
如範例所示,儘管DEVELOPERS
清單中沒有元素的os
等於“Windows”
,但斷言會通過,因為我們有一個元素 ( “Eric”
) 的languages
包含「 C
」。
因此, anyOf()
對應於「OR」邏輯:如果有任何元素的languages
包含「 C
」OR os
就是「 Windows
」。
相反, allOf()
執行“AND”邏輯。接下來,我們來看一個例子:
assertThat(DEVELOPERS, hasItem(
allOf(
hasProperty("languages", hasItem("C")),
hasProperty("os", is("Linux")),
hasProperty("age", greaterThan(25)))
));
在上面的測試中,我們檢查**DEVELOPERS
中的至少一個元素是否同時滿足allOf().
中的三個hasProperty()
Matcher
。**
由於「 Eric
」的屬性通過了三個hasProperty() Matcher
檢查,因此測試通過。
接下來,我們對測試進行一些更改:
assertThat(DEVELOPERS, not(hasItem( // <-- not() matcher
allOf(
hasProperty("languages", hasItem("C#")),
hasProperty("os", is("Linux")),
hasProperty("age", greaterThan(25)))
)));
這次,我們沒有匹配項,因為沒有元素可以通過所有三個hasProperty() Matcher
。
5.使用JUnit的assertTrue()
和Stream.anyMatch()
Harmcrest 提供了方便的方法來驗證清單中的元素是否具有特定屬性。或者,我們可以使用標準 JUnit assertTrue()
斷言和 Java Stream API 中的anyMatch()
來執行相同的檢查。
如果流中的任何元素通過檢查函數, anyMatch()
方法將傳回true
。接下來,我們來看一些例子:
assertTrue(DEVELOPERS.stream().anyMatch(dev -> dev.getOs().equals("Linux")));
assertTrue(DEVELOPERS.stream().anyMatch(dev -> dev.getAge() < 28));
assertTrue(DEVELOPERS.stream().anyMatch(dev -> dev.getLanguages().contains("Go")));
值得注意的是,當我們使用 lambda 來檢查元素的屬性時,我們可以直接呼叫 getter 方法來取得它們的值。這比 Hamcrest 的hasProperty()
Matcher
更容易,後者需要屬性名稱作為文字String
。
當然,如果需要,我們可以輕鬆擴展 lambda 表達式來進行複雜的檢查:
assertTrue(DEVELOPERS.stream().anyMatch(dev -> dev.getLanguages().contains("C") && dev.getOs().equals("Linux")));
上面的測試顯示了一個 lambda 表達式來檢查流中元素的多個屬性。
六,結論
在本文中,我們探索了使用 JUnit 和 Hamcrest 斷言清單是否包含具有某些屬性的元素的各種方法。
無論是使用簡單屬性還是組合多個條件,Hamcrest 都提供了一個強大的工具包來驗證集合中元素的屬性。此外,Hamcrest Matcher
使我們的測試更具可讀性和表現力,增強了測試程式碼的清晰度和可維護性。
或者,我們可以使用 Stream API 中的 JUnit assertTrue()
和anyMatch()
執行此類檢查。
與往常一樣,範例的完整原始程式碼可在 GitHub 上取得。