在具有特定 属性 的列表中仅存在一项的 Hamcrest 测试
Testing in Hamcrest that exists only one item in a list with a specific property
使用 Hamcrest,我们可以轻松地测试列表中是否存在 至少一个 项具有特定 属性,例如
List<Pojo> myList = ....
MatcherAssert.assertThat(myList, Matchers.hasItem(Matchers.<Pojo>hasProperty("fieldName", Matchers.equalTo("A funny string")))));
其中 class Pojo
类似于:
public class Pojo{
private String fieldName;
}
很好,但是我如何检查列表中是否只有一个对象具有特定属性?
您可能需要为此编写自己的匹配器。 (我更喜欢 fest assertions 和 Mockito,但过去常常使用 Hamcrest...)
例如...
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.core.IsCollectionContaining;
public final class CustomMatchers {
public static <T> Matcher<Iterable<? super T>> exactlyNItems(final int n, Matcher<? super T> elementMatcher) {
return new IsCollectionContaining<T>(elementMatcher) {
@Override
protected boolean matchesSafely(Iterable<? super T> collection, Description mismatchDescription) {
int count = 0;
boolean isPastFirst = false;
for (Object item : collection) {
if (elementMatcher.matches(item)) {
count++;
}
if (isPastFirst) {
mismatchDescription.appendText(", ");
}
elementMatcher.describeMismatch(item, mismatchDescription);
isPastFirst = true;
}
if (count != n) {
mismatchDescription.appendText(". Expected exactly " + n + " but got " + count);
}
return count == n;
}
};
}
}
您现在可以做...
List<TestClass> list = Arrays.asList(new TestClass("Hello"), new TestClass("World"), new TestClass("Hello"));
assertThat(list, CustomMatchers.exactlyNItems(2, hasProperty("s", equalTo("Hello"))));
列表为...时的示例失败输出...
List<TestClass> list = Arrays.asList(new TestClass("Hello"), new TestClass("World"));
...将会...
Exception in thread "main" java.lang.AssertionError:
Expected: a collection containing hasProperty("s", "Hello")
but: , property 's' was "World". Expected exactly 2 but got 1
(您可能需要稍微自定义一下)
顺便说一下,"TestClass" 是...
public static class TestClass {
String s;
public TestClass(String s) {
this.s = s;
}
public String getS() {
return s;
}
}
Matchers.hasItems
专门检查您提供的项目是否存在于集合中,您要查找的是 Matchers.contains
以确保 2 个集合基本相同 - 或者在您的集合中情况下,相当于根据提供
您还可以使用 Predicate<Pojo>
和 filter:
Predicate<Pojo> predicate = pojo -> pojo.getField().equals("funny string");
long nrOfElementsSatisfyingPredicate = myList.stream()
.filter(predicate::test)
.count();
assertEquals(1, nrOfElementsSatisfyingPredicate);
使用 Hamcrest,我们可以轻松地测试列表中是否存在 至少一个 项具有特定 属性,例如
List<Pojo> myList = ....
MatcherAssert.assertThat(myList, Matchers.hasItem(Matchers.<Pojo>hasProperty("fieldName", Matchers.equalTo("A funny string")))));
其中 class Pojo
类似于:
public class Pojo{
private String fieldName;
}
很好,但是我如何检查列表中是否只有一个对象具有特定属性?
您可能需要为此编写自己的匹配器。 (我更喜欢 fest assertions 和 Mockito,但过去常常使用 Hamcrest...)
例如...
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.core.IsCollectionContaining;
public final class CustomMatchers {
public static <T> Matcher<Iterable<? super T>> exactlyNItems(final int n, Matcher<? super T> elementMatcher) {
return new IsCollectionContaining<T>(elementMatcher) {
@Override
protected boolean matchesSafely(Iterable<? super T> collection, Description mismatchDescription) {
int count = 0;
boolean isPastFirst = false;
for (Object item : collection) {
if (elementMatcher.matches(item)) {
count++;
}
if (isPastFirst) {
mismatchDescription.appendText(", ");
}
elementMatcher.describeMismatch(item, mismatchDescription);
isPastFirst = true;
}
if (count != n) {
mismatchDescription.appendText(". Expected exactly " + n + " but got " + count);
}
return count == n;
}
};
}
}
您现在可以做...
List<TestClass> list = Arrays.asList(new TestClass("Hello"), new TestClass("World"), new TestClass("Hello"));
assertThat(list, CustomMatchers.exactlyNItems(2, hasProperty("s", equalTo("Hello"))));
列表为...时的示例失败输出...
List<TestClass> list = Arrays.asList(new TestClass("Hello"), new TestClass("World"));
...将会...
Exception in thread "main" java.lang.AssertionError:
Expected: a collection containing hasProperty("s", "Hello")
but: , property 's' was "World". Expected exactly 2 but got 1
(您可能需要稍微自定义一下)
顺便说一下,"TestClass" 是...
public static class TestClass {
String s;
public TestClass(String s) {
this.s = s;
}
public String getS() {
return s;
}
}
Matchers.hasItems
专门检查您提供的项目是否存在于集合中,您要查找的是 Matchers.contains
以确保 2 个集合基本相同 - 或者在您的集合中情况下,相当于根据提供
您还可以使用 Predicate<Pojo>
和 filter:
Predicate<Pojo> predicate = pojo -> pojo.getField().equals("funny string");
long nrOfElementsSatisfyingPredicate = myList.stream()
.filter(predicate::test)
.count();
assertEquals(1, nrOfElementsSatisfyingPredicate);