Hamcrest 匹配器在字符串列表中没有重复项?
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>
已替换
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())));
另一种选择是使用 hasDistinctElements()
matcher from 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>
实际上有一个实现的方法可以做到这一点 - doesNotHaveDuplicates
Assertions.assertThat(list).doesNotHaveDuplicates();
您可以参加测验并使用 Java 8 将其映射到问题并断言没有重复项
我为此实现了自己的匹配器。请注意错误消息对我来说没有正常工作(显示的是另一个条目而不是重复的条目)。我与社区共享代码(如果您想在您的产品中使用,请 link 和投票)
密码
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
,但应牢记内存要求。
任何其他基于集合的解决方案都会遇到同样的问题
我想要一个简单的 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>
已替换
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())));
另一种选择是使用 hasDistinctElements()
matcher from 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>
实际上有一个实现的方法可以做到这一点 - doesNotHaveDuplicates
Assertions.assertThat(list).doesNotHaveDuplicates();
您可以参加测验并使用 Java 8 将其映射到问题并断言没有重复项
我为此实现了自己的匹配器。请注意错误消息对我来说没有正常工作(显示的是另一个条目而不是重复的条目)。我与社区共享代码(如果您想在您的产品中使用,请 link 和投票)
密码
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
,但应牢记内存要求。
任何其他基于集合的解决方案都会遇到同样的问题