JUnit 和 hamcrest: containsInAnyOrder() 可以详细说明不匹配吗?

Ser*_*auk 5 java junit unit-testing hamcrest

Set使用 JUnit 和Hamcrest Matchers测试 a 时,我注意到该Matchers.contains()方法提供了一个很好的线索,说明测试出了什么问题。另一方面Matchers.containsInAnyOrder()差异报告几乎没有用。这是测试代码:

简单豆:

public class MyBean {
    private Integer id;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }       
}
Run Code Online (Sandbox Code Playgroud)

JUnit 测试:

import java.util.HashSet;
import java.util.Set;

import org.junit.Test;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

public class MyTest {

    @Test
    public void hamcrestTest() {
        Set<MyBean> beanSet = new HashSet<MyBean>();

        MyBean bean = new MyBean();
        bean.setId(1);
        beanSet.add(bean);

        bean = new MyBean();
        bean.setId(2);
        beanSet.add(bean);

        assertThat(beanSet, contains(
                hasProperty("id", is(1)),
                hasProperty("id", is(3))
                ));
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,实际的 bean id 是12而预期的id是13因此测试失败。

测试结果:

java.lang.AssertionError: 
Expected: iterable over [hasProperty("id", is <1>), hasProperty("id", is <3>)] in any order
     but: Not matched: <MyBean@4888884e
Run Code Online (Sandbox Code Playgroud)

如果我切换到Matchers.contains()方法,那么结果将提供更多信息:

java.lang.AssertionError: 
Expected: iterable containing [hasProperty("id", is <1>), hasProperty("id", is <3>)]
     but: item 0: property 'id' was <2>
Run Code Online (Sandbox Code Playgroud)

不幸的是,由于 Set 没有被排序,contains()在这种情况下不是一个选项。


最后的问题
在断言Setwith hamcrest时是否有可能获得更好的错误报告?

K E*_*son 2

对于如何报告containscontainsInAnyOrder匹配器的不匹配,Hamcrest 似乎有不同的实现。

通过执行以下操作,只需containsInAnyOrder为您提供该物品的价值:toString()

mismatchDescription.appendText("Not matched: ").appendValue(item);
Run Code Online (Sandbox Code Playgroud)

虽然contains匹配器通过委托给实际匹配器来做得更好describeMismatch()

matcher.describeMismatch(item, mismatchDescription);
Run Code Online (Sandbox Code Playgroud)

因此,在这种情况下您会看到hasProperty匹配器的附加信息,但在使用时不会看到containsInAnyOrder

toString()我认为在这种情况下你能做的最好的事情就是为你的班级实现一个MyBean

已经报告了一个与此相关的问题:https ://github.com/hamcrest/JavaHamcrest/issues/47