Hamcrest Matcher在字符串列表中没有重复项?

时间:2015-07-21 16:39:10

标签: java unit-testing junit hamcrest

我想要一个简单的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>

4 个答案:

答案 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,但要记住内存要求。

任何其他基于集合的解决方案都遇到相同的问题