我想要一个简单的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>
答案 0 :(得分:4)
实际上已经实现了一种方法 - doesNotHaveDuplicates
Assertions.assertThat(list).doesNotHaveDuplicates();
您可以参加测验并使用Java 8将其映射到问题并声明没有重复
答案 1 :(得分:3)
另一种选择是使用来自hasDistinctElements()
的Cirneco library匹配器(最后是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>
答案 2 :(得分:2)
替换
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())));
答案 3 :(得分:0)
我为此实现了自己的匹配器。请注意,错误消息对我而言不正确(显示的条目不同于重复的条目)。我与社区共享代码(如果要在产品中使用,请链接并赞扬)
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
,匹配器实例化一次,并由迭代的每个项目提供。根据{{1}}方法,它会告诉您该集合是否已经包含该项目,因此匹配是立即进行的。
Set.add
上述匹配器不适用于不受约束的惰性集合(例如,迭代器遍历数十亿条记录),因为assertThat(quizzes,(everyItem(hasProperty("questions",everyItem(hasProperty("question",is(distinct())))))));
拥有对对象的永久引用。可以轻松地将匹配器修改为仅拥有对象的Set
,但要记住内存要求。
任何其他基于集合的解决方案都遇到相同的问题