[英]Hamcrest Matcher for no duplicates in a List of Strings?
我想要一個簡單的hamcrest匹配器來查找List<String>
對象的重復項。 這就是我寫的
for (QuizEntity quiz : quizzes)
for (QuestionEntity question : quiz.getQuestions())
Assert.assertThat("There should be no duplicate questions", 1, Matchers.equalTo(Collections.frequency(questions, question.getQuestion())));
不幸的是我得到了這個輸出,這不夠描述。 任何
java.lang.AssertionError: There should be no duplicate questions
Expected: <20>
but: was <1>
實際上有一個實現的方法就是這樣做 - doesNotHaveDuplicates
Assertions.assertThat(list).doesNotHaveDuplicates();
您可以使用Java 8進行測驗並將其映射到問題,並斷言沒有重復
另一種選擇是使用來自Cirneco庫的 hasDistinctElements()
匹配器(最后是Hamcrest擴展)。
它可以使用如下:
Assert.assertThat("There should be no duplicate questions", questions, CirnecoMatchersJ7.hasDistinctElements());
雖然我建議這樣做
import static CirnecoMatchersJ7.*;
使其更具人性化
assertThat("There should be no duplicate questions", questions, hasDistinctElements());
Cirneco也有一些流利的代表,即
given(questions).withReason("There should be no duplicate questions").assertThat(hasDistinctElements());
可以按如下方式導入依賴項:
<dependency>
<groupId>it.ozimov</groupId>
<artifactId>java7-hamcrest-matchers</artifactId>
<version>0.7.0</version>
</dependency>
更換
Assert.assertThat("There should be no duplicate questions", 1, Matchers.equalTo(Collections.frequency(questions, question.getQuestion())));
同
Assert.assertThat("Question '" + question.getQuestion() + "' should not be duplicated", 1, Matchers.equalTo(Collections.frequency(questions, question.getQuestion())));
我為此實現了自己的匹配器。 請注意錯誤消息對我不正常(顯示另一個條目而不是重復條目)。 我與社區分享代碼(如果您想在產品中使用,請鏈接和upvote)
public static class DistinctMatcher<T> extends BaseMatcher<T>
{
private final Set<T> theSet = new HashSet<>();
public static <T> Matcher<? super T> distinct()
{
return new DistinctMatcher<T>();
}
@Override
public void describeTo(Description description)
{
description.appendText("has distinct values");
}
@Override
public void describeMismatch(Object item, Description description)
{
description.appendText("element found twice: ").appendValue(item);
}
@SuppressWarnings("unchecked")
@Override
public boolean matches(Object arg0)
{
return theSet.add((T) arg0);
}
}
通過維護有狀態的HashSet
,匹配器被實例化一次並由迭代的每個項目饋送。 根據Set.add
方法,它告訴您該集合是否包含該項目,因此匹配是立即的。
assertThat(quizzes,(everyItem(hasProperty("questions",everyItem(hasProperty("question",is(distinct())))))));
上面的匹配器不適用於無約束的惰性集合(例如迭代器超過數十億條記錄),因為Set
擁有對象的永久引用。 可以輕松修改匹配器以僅擁有對象的hashCode
,但應記住內存要求。
任何其他基於集合的解決方案都會遇到同樣的問題
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.